我々はEtime
に1秒を追加した場合、我々は['A', 'B']
によってグループ化することにより、結合する行を検索し、比較し、グループごとにすることができますが、次Stime
でEtime
のシフト:
df['Etime'] += pd.Timedelta(seconds=1)
df = df.sort_values(by=['A', 'B', 'Stime'])
df['keep'] = df.groupby(['A','B'])['Etime'].shift(1) != df['Stime']
# A B C Etime Stime keep
# 0 1220627 a 10.0 2016-05-29 18:10:00 2016-05-29 18:00:00 True
# 1 1220627 a 12.0 2016-05-29 18:27:00 2016-05-29 18:15:00 True
# 3 1220683 a 3.0 2016-05-29 18:39:00 2016-05-29 18:36:00 True
# 2 1220683 b 3.0 2016-05-29 18:39:00 2016-05-29 18:36:00 True
# 4 1220732 a 59.0 2016-05-29 18:59:00 2016-05-29 18:00:00 True
# 5 1220760 A 16.0 2016-05-29 18:40:00 2016-05-29 18:24:00 True
# 7 1220760 A 19.0 2016-05-29 18:59:00 2016-05-29 18:40:00 False
# 12 1220760 a 0.0 2016-05-29 18:10:00 2016-05-29 18:00:00 True
# 6 1220760 a 16.0 2016-05-29 18:40:00 2016-05-29 18:24:00 True
# 9 1220760 a 19.0 2016-05-29 18:59:00 2016-05-29 18:40:00 False
# 11 1220760 a 11.0 2016-05-29 19:10:00 2016-05-29 18:59:00 False
# 8 1220760 b 19.0 2016-05-29 18:59:00 2016-05-29 18:40:00 True
# 10 1220775 a 3.0 2016-05-29 18:06:00 2016-05-29 18:03:00 True
我々は、行を続けることになるでしょうkeep
がTrueでkeep
がFalseの行、 を削除することを除いて、Etime
を適切に更新したい場合を除きます。
['A', 'B', 'group_number']
でグループ化できるように、各行に「グループ番号」を割り当てることができたらうれしいですし、実際には可能です。私たちがやらなければならないことは、keep
列にcumsum
を適用されています。今、所望の結果が['A', 'B', 'group_number']
、 によってグループ化し、グループごとに最小Stime
と最大Etime
を見つけることによって見つけることができる
df['group_number'] = df.groupby(['A','B'])['keep'].cumsum()
# A B C Etime Stime keep group_number
# 0 1220627 a 10.0 2016-05-29 18:10:00 2016-05-29 18:00:00 True 1.0
# 1 1220627 a 12.0 2016-05-29 18:27:00 2016-05-29 18:15:00 True 2.0
# 3 1220683 a 3.0 2016-05-29 18:39:00 2016-05-29 18:36:00 True 1.0
# 2 1220683 b 3.0 2016-05-29 18:39:00 2016-05-29 18:36:00 True 1.0
# 4 1220732 a 59.0 2016-05-29 18:59:00 2016-05-29 18:00:00 True 1.0
# 5 1220760 A 16.0 2016-05-29 18:40:00 2016-05-29 18:24:00 True 1.0
# 7 1220760 A 19.0 2016-05-29 18:59:00 2016-05-29 18:40:00 False 1.0
# 12 1220760 a 0.0 2016-05-29 18:10:00 2016-05-29 18:00:00 True 1.0
# 6 1220760 a 16.0 2016-05-29 18:40:00 2016-05-29 18:24:00 True 2.0
# 9 1220760 a 19.0 2016-05-29 18:59:00 2016-05-29 18:40:00 False 2.0
# 11 1220760 a 11.0 2016-05-29 19:10:00 2016-05-29 18:59:00 False 2.0
# 8 1220760 b 19.0 2016-05-29 18:59:00 2016-05-29 18:40:00 True 1.0
# 10 1220775 a 3.0 2016-05-29 18:06:00 2016-05-29 18:03:00 True 1.0
:
result = df.groupby(['A','B', 'group_number']).agg({'Stime':'min', 'Etime':'max'})
Stime Etime
A B group_number
1220627 a 1.0 2016-05-29 18:00:00 2016-05-29 18:10:00
2.0 2016-05-29 18:15:00 2016-05-29 18:27:00
1220683 a 1.0 2016-05-29 18:36:00 2016-05-29 18:39:00
b 1.0 2016-05-29 18:36:00 2016-05-29 18:39:00
1220732 a 1.0 2016-05-29 18:00:00 2016-05-29 18:59:00
1220760 A 1.0 2016-05-29 18:24:00 2016-05-29 18:59:00
a 1.0 2016-05-29 18:00:00 2016-05-29 18:10:00
2.0 2016-05-29 18:24:00 2016-05-29 19:10:00
b 1.0 2016-05-29 18:40:00 2016-05-29 18:59:00
1220775 a 1.0 2016-05-29 18:03:00 2016-05-29 18:06:00
一緒にすべてを置く
、
import numpy as np
import pandas as pd
df = pd.DataFrame(
{'A': [1220627, 1220627, 1220683, 1220683, 1220732, 1220760, 1220760,
1220760, 1220760, 1220760, 1220775, 1220760, 1220760],
'B': ['a', 'a', 'b', 'a', 'a', 'A', 'a', 'A', 'b', 'a', 'a', 'a', 'a'],
'C': [10.0, 12.0, 3.0, 3.0, 59.0, 16.0, 16.0, 19.0, 19.0, 19.0, 3.0, 11.0, 0],
'Stime': ['18:00:00', '18:15:00', '18:36:00', '18:36:00', '18:00:00',
'18:24:00', '18:24:00', '18:40:00', '18:40:00', '18:40:00',
'18:03:00', '18:59:00', '18:00:00'],
'Etime': ['18:09:59', '18:26:59', '18:38:59', '18:38:59', '18:58:59',
'18:39:59', '18:39:59', '18:58:59', '18:58:59', '18:58:59',
'18:05:59', '19:09:59', '18:09:59'],})
for col in ['Stime', 'Etime']:
df[col] = pd.to_datetime(df[col])
df['Etime'] += pd.Timedelta(seconds=1)
df = df.sort_values(by=['A', 'B', 'Stime'])
df['keep'] = df.groupby(['A','B'])['Etime'].shift(1) != df['Stime']
df['group_number'] = df.groupby(['A','B'])['keep'].cumsum()
result = df.groupby(['A','B', 'group_number']).agg({'Stime':'min', 'Etime':'max'})
result = result.reset_index()
result['C'] = (result['Etime']-result['Stime']).dt.total_seconds()/60.0
result = result[['A', 'B', 'C', 'Stime', 'Etime']]
print(result)
[start, end]
は、2つの間隔当接し、
end
一方の等しいことである代わりに、完全に閉じた間隔の 収率形態[start, end)
の半開区間を使用する利点の
A B C Stime Etime
0 1220627 a 10.0 2016-05-29 18:00:00 2016-05-29 18:10:00
1 1220627 a 12.0 2016-05-29 18:15:00 2016-05-29 18:27:00
2 1220683 a 3.0 2016-05-29 18:36:00 2016-05-29 18:39:00
3 1220683 b 3.0 2016-05-29 18:36:00 2016-05-29 18:39:00
4 1220732 a 59.0 2016-05-29 18:00:00 2016-05-29 18:59:00
5 1220760 A 35.0 2016-05-29 18:24:00 2016-05-29 18:59:00
6 1220760 a 10.0 2016-05-29 18:00:00 2016-05-29 18:10:00
7 1220760 a 46.0 2016-05-29 18:24:00 2016-05-29 19:10:00
8 1220760 b 19.0 2016-05-29 18:40:00 2016-05-29 18:59:00
9 1220775 a 3.0 2016-05-29 18:03:00 2016-05-29 18:06:00
つstart
次の
もう1つの利点は、半開き間隔の分数が end-start
に等しいことです。完全に閉じた間隔では、数式はend-start+1
になります。
Pythonの組み込みrange
とリストスライス構文では、半開きの間隔for these same reasonsを使用しています。だから私は [Stime, Etime)
あなたのDataFrameに半開きの間隔を使用することをお勧めします も。
は、列Bの文字ケース物質のでしょうか? 'A'は 'a'と同じですか? – piRSquared
いいえ、それは同じではありません。事件は重要です。 –