我有一个像这样的表:
| date | activity |
|---------------------|----------|
| 2017-03-30 01:00:00 | 1 |
| 2017-03-30 01:00:30 | 1 |
| 2017-03-30 01:01:00 | 1 |
| 2017-03-30 01:01:30 | 2 |
| 2017-03-30 01:02:00 | 2 |
| 2017-03-30 01:02:30 | 2 |
| 2017-03-30 01:03:00 | 1 |
我的最终目标是从该时间序列中得出活动1的一些统计信息。为此,我需要从构造一个列表开始,该列表将汇总有关活动的信息。
基本上,我想为每个块(标记为1的连续行的块)获取一个元组,其中该元组将包含该块的开始日期以及其中的行总数。 对于前面的示例,相应的列表为:
[(2017-03-30 01:00:00,3),(2017-03-30 01:03:00,1)]
关于如何实现此目标的任何想法?我也愿意接受最终会产生相同信息的其他建议。
答案 0 :(得分:2)
通过cumsum
+比较shift
完成具有相同连续值的查找组。使用where
忽略不需要的组。
#df = df.sort_values('date')
s = df.activity.ne(df.activity.shift(1)).cumsum()
res = df.groupby(s.where(df.activity.eq(1)).rename(None)).date.agg(['first', 'size'])
输出:
first size
1.0 2017-03-30 01:00:00 3
3.0 2017-03-30 01:03:00 1
如果您真的想要元组列表,则:
[tuple(x) for x in res.to_numpy()]
#[('2017-03-30 01:00:00', 3), ('2017-03-30 01:03:00', 1)]
答案 1 :(得分:1)
更易消化,但熊猫风格可能更少:
如果您随后想要获取所要查找的元组列表,则可以在末尾使用.iterrows()
:
df['id'] = (df['activity'].shift(1) != df['activity']).cumsum()
inds = df['activity'] == 1
df = df.loc[inds, :]
result = df.groupby('id')['date'].agg(['min', 'size])
result
# id size min
# 1 3 2017-03-30 01:00:00
# 3 1 2017-03-30 01:03:00
对于元组列表,您可以执行以下操作:
[(row[1][1], row[1][0]) for row in result.iterrows()]
答案 2 :(得分:0)
您可以先为每个组分配一个号码,然后使用groupby
。第一部分不是那个pythonic,而是有效的:
import pandas as pd
df = {'date': {0: '2017-03-30 01:00:00',
1: '2017-03-30 01:00:30',
2: '2017-03-30 01:01:00',
3: '2017-03-30 01:01:30',
4: '2017-03-30 01:02:00',
5: '2017-03-30 01:02:30',
6: '2017-03-30 01:03:00'},
'activity': {0: 1, 1: 1, 2: 1, 3: 2, 4: 2, 5: 2, 6: 1}}
df = pd.DataFrame(df)
# add group
group = 0
groups = []
initial_value = df.iloc[0]["activity"]
for _, row in df.iterrows():
if row["activity"]!= initial_value:
initial_value = row["activity"]
group +=1
groups.append(group)
df["group"] = groups
# count and min date
out = df.groupby(["group", "activity"])\
.agg({"date":{"min", "count"}})
out.columns = ["_".join(o) for o in out.columns]
out = out.reset_index()