2016-05-06 8 views
0

私はExcelから売買取引テーブルを読みました。最初のアイテムが売られてから1時間以内に売り上げを知りたいと思っています。 Aを販売レポートにして、Bを作成します。Pythonを使用して制限時間内に行を取得する方法は?

A= 
item Location time 
X  Canada  10:03:18 
X  Canada  10:08:38 
X  Canada  10:24:46 
X  Canada  11:16:35 
X  US   10:00:16 
X  US   11:52:12 
Y  Canada  2:08:38 
Y  Canada  4:01:48 
Y  US   13:32:02 
Y  US   14:07:03 

B= 
item location first sale count 
X  Canada  10:03:18 3 
X  US   10:00:16 1 
Y  Canada  2:08:38  1 
Y  US   13:32:02 2 

これは私がやったことです:

A= A.sort('time', ascending=True).reset_index() 
sale_loc= pd.DataFrame(A.groupby(['item', 'Location'], sort = False).first()).reset_index() 
for i in sale_loc.index: 
    sale_cutoff = (A.time[i] + dt.timedelta(hours=1)).time 

しかし、私は時間を操作部にエラーが発生します。私は、異なる機能を試みたが、私はまた、代わりにループの新しい列A(時間+ 1時間)が、同様の問題を追加してみました...

答えて

0
import numpy as np 
import pandas as pd 

df = pd.DataFrame({'Location': ['Canada', 'Canada', 'Canada', 'Canada', 'US', 'US', 'Canada', 'Canada', 'US', 'US'], 'item': ['X', 'X', 'X', 'X', 'X', 'X', 'Y', 'Y', 'Y', 'Y'], 'time': ['10:03:18', '10:08:38', '10:24:46', '11:16:35', '10:00:16', '11:52:12', '2:08:38', '4:01:48', '13:32:02', '14:07:03']}) 

df['start'] = pd.to_datetime(df['time']) 
grouped = df.groupby(['item', 'Location']) 
df['end'] = (grouped['start'].transform(lambda grp: grp.min()+pd.Timedelta(hours=1))) 
df['mask'] = (df['start'] < df['end']) 

result = grouped['mask'].sum() 
print(result) 

利回り

item Location 
X  Canada  3.0 
     US   1.0 
Y  Canada  1.0 
     US   2.0 
Name: mask, dtype: float64 

メインアイデアはitemLocationによってグループにあり、各グループの最小の開始時間を見つけ、その後、1時間を追加します。

df['end'] = (grouped['start'].transform(lambda grp: grp.min()+pd.Timedelta(hours=1))) 

transformdfと同じ長さのシリーズを返すので、各行が値を取得します。

In [319]: df 
Out[319]: 
    Location item  time    start     end 
0 Canada X 10:03:18 2016-05-06 10:03:18 2016-05-06 11:03:18 
1 Canada X 10:08:38 2016-05-06 10:08:38 2016-05-06 11:03:18 
2 Canada X 10:24:46 2016-05-06 10:24:46 2016-05-06 11:03:18 
3 Canada X 11:16:35 2016-05-06 11:16:35 2016-05-06 11:03:18 
4  US X 10:00:16 2016-05-06 10:00:16 2016-05-06 11:00:16 
5  US X 11:52:12 2016-05-06 11:52:12 2016-05-06 11:00:16 
6 Canada Y 2:08:38 2016-05-06 02:08:38 2016-05-06 03:08:38 
7 Canada Y 4:01:48 2016-05-06 04:01:48 2016-05-06 03:08:38 
8  US Y 13:32:02 2016-05-06 13:32:02 2016-05-06 14:32:02 
9  US Y 14:07:03 2016-05-06 14:07:03 2016-05-06 14:32:02 

今、あなたは簡単に興味の行を識別することができます。 startend未満のものであり、それら:

In [320]: df['mask'] = (df['start'] < df['end']) 
In [321]: df 
Out[321]: 
    Location item  time    start     end mask 
0 Canada X 10:03:18 2016-05-06 10:03:18 2016-05-06 11:03:18 True 
1 Canada X 10:08:38 2016-05-06 10:08:38 2016-05-06 11:03:18 True 
2 Canada X 10:24:46 2016-05-06 10:24:46 2016-05-06 11:03:18 True 
3 Canada X 11:16:35 2016-05-06 11:16:35 2016-05-06 11:03:18 False 
4  US X 10:00:16 2016-05-06 10:00:16 2016-05-06 11:00:16 True 
5  US X 11:52:12 2016-05-06 11:52:12 2016-05-06 11:00:16 False 
6 Canada Y 2:08:38 2016-05-06 02:08:38 2016-05-06 03:08:38 True 
7 Canada Y 4:01:48 2016-05-06 04:01:48 2016-05-06 03:08:38 False 
8  US Y 13:32:02 2016-05-06 13:32:02 2016-05-06 14:32:02 True 
9  US Y 14:07:03 2016-05-06 14:07:03 2016-05-06 14:32:02 True 
itemLocationでもう一度グループ化

、望ましい結果が倍maskの数を合計することによって発見された各グループのために真である:

result = grouped['mask'].sum() 
+0

完全な答えをいただきありがとうございます。私は、このアプローチを最初に試したときに私が見逃していたと思います。うまくいく! – Ana

1

コード全体を生成するのではなく、エラーを投げていたセクションに焦点を当てました。

sale_time = ['10:03:18', '10:08:38', '11:16:35', '10:00:16'] 

import datetime 
for i in sale_time: 
    sale_time1 = datetime.time(hour = int(i[0:2]), minute=int(i[3:5]), second=int(i[6:8])) 
    print(sale_time1) 
    sale_cutoff = datetime.time(sale_time1.hour+1, sale_time1.minute, sale_time1.second) 
    print(sale_cutoff) 
+0

ありがとう@mjp、それはループのアプローチで時間操作の問題を修正します。 – Ana

+0

ちょっと@Ana、うれしかったよ。 P.S.あなたの編集は完全に正しい - そこに命名の矛盾があった。なぜ人々がそれを拒否したのか考えられません。一貫性のために投稿を編集しました – mjp

関連する問題