Python 数据帧查找间隔并计算发生次数
我得到了一份不同事件的列表,其中有混合事件。例如,事件1可能会发生三次,然后另一个事件以及稍后的事件1将再次发生 我需要的是每个事件的间隔以及这些间隔内该事件的发生次数Python 数据帧查找间隔并计算发生次数,python,pandas,dataframe,pandas-groupby,Python,Pandas,Dataframe,Pandas Groupby,我得到了一份不同事件的列表,其中有混合事件。例如,事件1可能会发生三次,然后另一个事件以及稍后的事件1将再次发生 我需要的是每个事件的间隔以及这些间隔内该事件的发生次数 values = { '2017-11-28 11:00': 'event1', '2017-11-28 11:01': 'event1', '2017-11-28 11:02': 'event1', '2017-11-28 11:03': 'event2',
values = {
'2017-11-28 11:00': 'event1',
'2017-11-28 11:01': 'event1',
'2017-11-28 11:02': 'event1',
'2017-11-28 11:03': 'event2',
'2017-11-28 11:04': 'event2',
'2017-11-28 11:05': 'event1',
'2017-11-28 11:06': 'event1',
'2017-11-28 11:07': 'event1',
'2017-11-28 11:08': 'event3',
'2017-11-28 11:09': 'event3',
'2017-11-28 11:10': 'event2',
}
import pandas as pd
df = pd.DataFrame.from_dict(values, orient='index').reset_index()
df.columns = ['time', 'event']
df['time'] = df['time'].apply(pd.to_datetime)
df.set_index('time', inplace=True)
df.sort_index(inplace=True)
df.head()
#%% first solution
# create intervals and count occurrences per interval
df['interval'] = (df['event'] != df['event'].shift(1)).astype(int).cumsum()
df['count'] = df.groupby(['event', 'interval']).cumcount() + 1
# now group by intervals
df.groupby('interval').last()
#%% second solution
df = df.reset_index()
# create intervals
df = df.groupby(df['event'].ne(df['event'].shift()).cumsum())
# calc start/end times and count occurances at the same time
df.apply(lambda x: pd.DataFrame({
'start':[x['time'].min()],
'end':[x['time'].max()],
'event':[x['event'].iloc[0]],
'count':[len(x)]})).reset_index(drop=True)
预期结果是:
occurrences = [
{'start':'2017-11-28 11:00',
'end':'2017-11-28 11:02',
'event':'event1',
'count':3},
{'start':'2017-11-28 11:03',
'end':'2017-11-28 11:04',
'event':'event2',
'count':2},
{'start':'2017-11-28 11:05',
'end':'2017-11-28 11:07',
'event':'event1',
'count':3},
{'start':'2017-11-28 11:08',
'end':'2017-11-28 11:09',
'event':'event3',
'count':2},
{'start':'2017-11-28 11:10',
'end':'2017-11-28 11:10',
'event':'event2',
'count':1},
]
我正在考虑使用pd.merge\u asof查找间隔的开始/结束时间,并使用pd.cut()进行分组和计数。但不知怎的,我被卡住了。感谢您的帮助。尝试以下方法:
In [68]: x = df.reset_index()
In [69]: (x.groupby(x.event.ne(x.event.shift()).cumsum())
...: .apply(lambda x:
...: pd.DataFrame({
...: 'start':[x['time'].min()],
...: 'end':[x['time'].min()],
...: 'event':[x['event'].iloc[0]],
...: 'count':[len(x)]})
...: )
...: .reset_index(drop=True)
...: .to_dict('r')
...: )
Out[69]:
[{'count': 3,
'end': Timestamp('2017-11-28 11:00:00'),
'event': 'event1',
'start': Timestamp('2017-11-28 11:00:00')},
{'count': 2,
'end': Timestamp('2017-11-28 11:03:00'),
'event': 'event2',
'start': Timestamp('2017-11-28 11:03:00')},
{'count': 3,
'end': Timestamp('2017-11-28 11:05:00'),
'event': 'event1',
'start': Timestamp('2017-11-28 11:05:00')},
{'count': 2,
'end': Timestamp('2017-11-28 11:08:00'),
'event': 'event3',
'start': Timestamp('2017-11-28 11:08:00')},
{'count': 1,
'end': Timestamp('2017-11-28 11:10:00'),
'event': 'event2',
'start': Timestamp('2017-11-28 11:10:00')}]
或者,如果希望将时间
列作为字符串,请执行以下操作:
In [75]: (x.groupby(x.event.ne(x.event.shift()).cumsum())
...: .apply(lambda x:
...: pd.DataFrame({
...: 'start':[x['time'].min().strftime('%Y-%m-%d %H:%M:%S')],
...: 'end':[x['time'].min().strftime('%Y-%m-%d %H:%M:%S')],
...: 'event':[x['event'].iloc[0]],
...: 'count':[len(x)]})
...: )
...: .reset_index(drop=True)
...: .to_dict('r')
...: )
Out[75]:
[{'count': 3,
'end': '2017-11-28 11:00:00',
'event': 'event1',
'start': '2017-11-28 11:00:00'},
{'count': 2,
'end': '2017-11-28 11:03:00',
'event': 'event2',
'start': '2017-11-28 11:03:00'},
{'count': 3,
'end': '2017-11-28 11:05:00',
'event': 'event1',
'start': '2017-11-28 11:05:00'},
{'count': 2,
'end': '2017-11-28 11:08:00',
'event': 'event3',
'start': '2017-11-28 11:08:00'},
{'count': 1,
'end': '2017-11-28 11:10:00',
'event': 'event2',
'start': '2017-11-28 11:10:00'}]
这里有两个解决方案。第一个是基于和提供的链接。它为间隔创建连续的数字,并累计统计这些间隔内的事件
values = {
'2017-11-28 11:00': 'event1',
'2017-11-28 11:01': 'event1',
'2017-11-28 11:02': 'event1',
'2017-11-28 11:03': 'event2',
'2017-11-28 11:04': 'event2',
'2017-11-28 11:05': 'event1',
'2017-11-28 11:06': 'event1',
'2017-11-28 11:07': 'event1',
'2017-11-28 11:08': 'event3',
'2017-11-28 11:09': 'event3',
'2017-11-28 11:10': 'event2',
}
import pandas as pd
df = pd.DataFrame.from_dict(values, orient='index').reset_index()
df.columns = ['time', 'event']
df['time'] = df['time'].apply(pd.to_datetime)
df.set_index('time', inplace=True)
df.sort_index(inplace=True)
df.head()
#%% first solution
# create intervals and count occurrences per interval
df['interval'] = (df['event'] != df['event'].shift(1)).astype(int).cumsum()
df['count'] = df.groupby(['event', 'interval']).cumcount() + 1
# now group by intervals
df.groupby('interval').last()
#%% second solution
df = df.reset_index()
# create intervals
df = df.groupby(df['event'].ne(df['event'].shift()).cumsum())
# calc start/end times and count occurances at the same time
df.apply(lambda x: pd.DataFrame({
'start':[x['time'].min()],
'end':[x['time'].max()],
'event':[x['event'].iloc[0]],
'count':[len(x)]})).reset_index(drop=True)
第二种解决方案是基于上面给出的答案。与第一个想法类似,它还创建了间隔编号,但也找到了此类间隔的开始/结束时间戳
values = {
'2017-11-28 11:00': 'event1',
'2017-11-28 11:01': 'event1',
'2017-11-28 11:02': 'event1',
'2017-11-28 11:03': 'event2',
'2017-11-28 11:04': 'event2',
'2017-11-28 11:05': 'event1',
'2017-11-28 11:06': 'event1',
'2017-11-28 11:07': 'event1',
'2017-11-28 11:08': 'event3',
'2017-11-28 11:09': 'event3',
'2017-11-28 11:10': 'event2',
}
import pandas as pd
df = pd.DataFrame.from_dict(values, orient='index').reset_index()
df.columns = ['time', 'event']
df['time'] = df['time'].apply(pd.to_datetime)
df.set_index('time', inplace=True)
df.sort_index(inplace=True)
df.head()
#%% first solution
# create intervals and count occurrences per interval
df['interval'] = (df['event'] != df['event'].shift(1)).astype(int).cumsum()
df['count'] = df.groupby(['event', 'interval']).cumcount() + 1
# now group by intervals
df.groupby('interval').last()
#%% second solution
df = df.reset_index()
# create intervals
df = df.groupby(df['event'].ne(df['event'].shift()).cumsum())
# calc start/end times and count occurances at the same time
df.apply(lambda x: pd.DataFrame({
'start':[x['time'].min()],
'end':[x['time'].max()],
'event':[x['event'].iloc[0]],
'count':[len(x)]})).reset_index(drop=True)
您是否只寻找基于熊猫的解决方案?对于非基于pandas的解决方案,您可以对其进行迭代。我打赌有一个很好的pandas解决方案。我发现这是基于迭代的。但是熊猫会更好。你甚至可以看看这里,@VivekHarikrishnan,这是个好主意。良好的起点。问题在于如何按时间间隔对它们进行分组——也就是说,您如何知道何时达到了时间间隔的最高累计计数?附言:我找到了解决办法。如果你发你的,我会接受的。根据@chrisb在@Vivek Harkrishnan提到的问题中的回答,你可以在
block
上执行groupby
,然后选择min('time')
作为start
和max('time')
asend