2016-11-11 5 views
4

私は以下の表のようなpythonでデータのリストを持っています。列のカテゴリごとの時間を計算するために、すべてのデータ行を繰り返し処理する必要がありますか?

基本的には、私たちの迷路/アリーナでロボットが何をしているかを観察することによって生成されます。イベントのタイムスタンプはありますが、タイムスタンプはイベント駆動型であり、周期的ではありません。

各アリーナで費やされる時間を効率的に見つける必要があります。

TimeStamp Arena 
101   Arena A 
109   Arena A 
112   Arena B 
113   Arena A 
118   Arena A 
120   Arena D 
125   Arena D 
129   Arena D 
138   Arena B 
139   Arena B 
148   Arena C 
149   Arena C 
150   Arena B 
151   Arena B 
159   Arena D 
169   Arena D 
171   Arena D 
172   Arena D 
175   Arena B 
177   Arena B 
180   Arena B 
181   Arena A 
182   Arena A 
189   Arena E 
200   Arena E 
204   Arena E 
208   Arena A 
209   Arena A 

基本的には、これを取得する必要があります。各アリーナで費やされた合計時間。

Arena TimeStamp 
Arena D   32 
Arena B   23 
Arena E   22 
Arena A   16 
Arena C   10 

私は今これを行う簡単なスクリプトを書いています。

import pandas as pd 

data = pd.read_csv('arenas_visited.csv') 


l = len(data[[1]]) 
first_arena = data.loc[0, 'Arena'] 
start_time = data.loc[0, 'TimeStamp'] 

summary = [] 

for i in range(0,l): 

try: 
    next_arena = data.loc[i+1, 'Arena'] 
except: 
    break  

first_arena = data.loc[i, 'Arena'] 

if first_arena != next_arena: 

    change_time = data.loc[i, 'TimeStamp'] 
    time_spent = change_time - start_time 
    arena = str(data.loc[i, 'Arena']) 
    summary.append([arena, time_spent]) 
    start_time = change_time 
    first_arena = data.loc[i+1, 'Arena'] 

    if i == l-2: 
     if data.loc[i, 'Arena'] != data.loc[i+1, 'Arena']: 
      time_spent = 1 
      arena = str(data.loc[i+1, 'Arena']) 
      print (str(1) + " Spent in " + arena) 
      summary.append([arena, time_spent]) 

else: 
    pass 

aggregated = pd.DataFrame(summary, columns = ['Arena', 'TimeStamp']) 
time_per_arena = aggregated.groupby(['Arena']).sum().sort_values('TimeStamp', ascending=False).reset_index() 
print time_per_arena 

基本的に、これは十分に機能しますが、しかし、最終的にはこのデータの文字通り何百万もの行があり、これを行うためのより速い方法を理解する必要があります。

ただし、すべての行を繰り返し処理する以外の方法はありません。

私が検討していないものはありますか?

+0

すべてのあなたが必要な場合は


遷移は次のアリーナに行く場所あなたがそれをしたい場合は、マイナーな編集は、私たちの横断を逆にすることによってこれを提供しますアリーナによる要約ですが、なぜあなたはそれを計算していませんか? – TemporalWolf

+0

私はタイムスタンプの違いを取得する必要があります、それらをグループ化すると、私は部屋に入ったり、部屋を去っているかわからないので動作しません。 –

答えて

2

時間デルタのベクトルを作成し、それに対するグループと合計:

df['delta'] = df.TimeStamp - df.TimeStamp.shift() 

df.groupby('Arena').delta.sum() 
Out[62]: 
Arena 
Arena_A 21.0 
Arena_B 23.0 
Arena_C 10.0 
Arena_D 32.0 
Arena_E 22.0 
Name: delta, dtype: float64 
+0

これは潜在的に有用と思われる。私のデータに対してこれを実行したのですか、これは単なるサンプルですか?答えが異なるからです。私は私の中にいくつかのバグを見つけましたが、私はこの方法をテストし、これがうまくいくかどうかを知らせます。ありがとうBoud! –

+0

上記のデータを簡単にコピーして貼り付けます。あなたがベクトル化された方法で達成しようとしている数学は、私があなたに説明するものです。あなたが達成しようとしていることの説明が十分であるため、私はあなたのコードを読まなかった。 – Boud

+0

ありがとう、私はなぜArena_Aのために、あなたは21を持っていると私は16を持っているか把握しようとしています... –

0

Pythonは他の言語が自動的に組み込まれていないことを素敵なものの束を持っています。ときにすることができ、インデックスにない理由は自分でデータを通じてありません:

result = {} 
old_arena = None 
old_timestamp = 0 
# I don't have a lot of experience with panda, so you may need to massage the 
# input to be able to do this 
for line in data: 
    timestamp, _, arena = line.split() 
    if arena == old_arena: 
     continue 
    timestamp = int(timestamp) 
    try: 
     result[old_arena] += timestamp - old_timestamp 
    except: 
     result[old_arena] = timestamp - old_timestamp 

    old_arena = arena 
    old_timestamp = timestamp 

# Process the last interval - if the last one was changed, then 
# old_timestamp will equal timestamp and this is fine  
result[old_arena] += int(timestamp) - old_timestamp 

これは、kはアリーナの数であるO(n)時間& O(n+k)スペースの複雑さと全体のリストに、単一の時間を処理します。あなたの例のデータの場合

{'A': 27, 'C': 2, 'B': 26, 'E': 19, 'D': 34, None: 101} 

:これはold_arenaへの遷移を与えることは注目に値します、どの(いずれも初期オフセット時間を表していない)を含む辞書可能と

結果にあなたが望むものではないかもしれません。

result = {} 
old_arena = None 
old_timestamp = 0 
# I don't have a lot of experience with panda, so you may need to massage the 
# input to be able to do this 
for line in reversed(data): 
    timestamp, _, arena = line.split() 
    if arena == old_arena: 
     continue 
    timestamp = int(timestamp) 
    try: 
     result[old_arena] += old_timestamp - timestamp 
    except: 
     result[old_arena] = old_timestamp - timestamp 

    old_arena = arena 
    old_timestamp = timestamp 

# Process the last interval - if the last one was changed, then 
# old_timestamp will equal timestamp and this is fine  
result[old_arena] += old_timestamp - int(timestamp) 

います:

{'A': 21, 'C': 10, 'B': 23, 'E': 22, 'D': 32, None: -209} 
+0

非常に興味深い解決策。今すぐテスト! –

+0

@StacyGarfield逆解決策を追加しました。ここで、トランジションは新しいアリーナに移動します。 – TemporalWolf

+0

@StacyGarfield最後の間隔を追加できないバグを修正しました – TemporalWolf

関連する問題