4

タプルの最初の部分がタイムスタンプで、2 番目の部分が値である 2 つのタプルのリストで構成されるタイムライン/時系列があります。タプルはタイムスタンプ順に並べられます。

現在、これらのタイムラインが 2 つあり、それらを互いに分割する必要があります。これは、同じタイムスタンプの両方のタイムラインで値を取得した場合、それらを分割する必要があることを意味します。タイムスタンプのいずれかのタイムラインに値がない場合は、0 を想定する必要があります。ゼロによる除算が発生した場合 (その場合のみ)、NaN を想定する必要があります。タイムスタンプには大きなギャップがあります。つまり、min(timestamp) から max(timestamp) まで繰り返すことは解決策ではありません。

私は、非常に非pythonicで実行時間が短いソリューションを構築しました。タイムラインには約 100 万のエントリがあるため、パフォーマンスは私にとって重要です。私の解決策は、両方のリストがソートされていることを利用していません。

はいの場合、より良い解決策はありますか?

#!/usr/bin/env python

l1 = [(1, 100), (2, 1000),           (4, 1500), (5, 5400),          (7, 7800)]
l2 = [(1, 20),  (2, 400),  (3, 240), (4, 500),  (5, 100),  (6, 27),          ]
ex = [(1, 5),   (2, 2),    (3, 0),   (4, 3),    (5, 54),   (6, 0),  (7, float('NaN'))]

def f(l1, l2):
  #Turn to dicts:
  l1d = dict(l1)
  l2d = dict(l2)

  #Compute Keyspace
  keys = set(l1d.keys()).union(set(l2d.keys()))

  result = []
  for key in keys:
    if not key in l2d:
      result.append((key, float('NaN')))
    elif key not in l1d:
      result.append((key, 0))
    else:
      result.append((key, l1d[key]/l2d[key])) 

  return result

r = f(l1, l2)

print("L1: %s" % (l1))
print("L2: %s" % (l2))
print("")
print("Expected: %s" % (ex))
print("Result: %s" % (r))
4

1 に答える 1

3

パフォーマンスが必要な場合は、pandasをご覧ください。

import pandas as pd

l1 = [(1, 100), (2, 1000),           (4, 1500), (5, 5400),          (7, 7800)]
l2 = [(1, 20),  (2, 400),  (3, 240), (4, 500),  (5, 100),  (6, 27),          ]

s1 = pd.Series(dict(l1))
s2 = pd.Series(dict(l2))

非常に明示的な数学的操作になりました。

s1 / s2

戻り値

1     5.0
2     2.5
3     NaN
4     3.0
5    54.0
6     NaN
7     NaN

NaNに存在する場合はゼロに置き換えたい場合l2

s1.reindex(s1.index|s2.index).fillna(0) / s2


1     5.0
2     2.5
3     0.0
4     3.0
5    54.0
6     0.0
7     NaN

百万件のエントリに対しても完全に機能します。インデックスで日時を使用し、日時を指定して操作できます。

于 2013-06-20T09:11:00.323 に答える