Python Pandas - 查找具有最大聚合值的连续组
Posted
技术标签:
【中文标题】Python Pandas - 查找具有最大聚合值的连续组【英文标题】:Python Pandas - find consecutive group with max aggregate values 【发布时间】:2017-07-07 14:03:33 【问题描述】:我有一个包含日期时间和整数的数据框
import numpy as np
import pandas as pd
df = pd.DataFrame()
df['dt'] = pd.date_range("2017-01-01 12:00", "2017-01-01 12:30", freq="1min")
df['val'] = np.random.choice(xrange(1, 100), df.shape[0])
给我
dt val
0 2017-01-01 12:00:00 33
1 2017-01-01 12:01:00 42
2 2017-01-01 12:02:00 44
3 2017-01-01 12:03:00 6
4 2017-01-01 12:04:00 70
5 2017-01-01 12:05:00 94*
6 2017-01-01 12:06:00 42*
7 2017-01-01 12:07:00 97*
8 2017-01-01 12:08:00 12
9 2017-01-01 12:09:00 11
10 2017-01-01 12:10:00 66
11 2017-01-01 12:11:00 71
12 2017-01-01 12:12:00 25
13 2017-01-01 12:13:00 23
14 2017-01-01 12:14:00 39
15 2017-01-01 12:15:00 25
我怎样才能找到N
-minute 组连续 dt
给我val
的最大总和?
在这种情况下,如果N=3
,那么结果应该是:
dt val
5 2017-01-01 12:05:00 94
6 2017-01-01 12:06:00 42
7 2017-01-01 12:07:00 97
(上面标有星号)
【问题讨论】:
【参考方案1】:您可以使用rolling/sum
和np.nanargmax
来查找与最大值的第一次出现关联的索引:
import numpy as np
import pandas as pd
df = pd.DataFrame('dt': ['2017-01-01 12:00:00', '2017-01-01 12:01:00', '2017-01-01 12:02:00', '2017-01-01 12:03:00', '2017-01-01 12:04:00', '2017-01-01 12:05:00', '2017-01-01 12:06:00', '2017-01-01 12:07:00', '2017-01-01 12:08:00', '2017-01-01 12:09:00', '2017-01-01 12:10:00', '2017-01-01 12:11:00', '2017-01-01 12:12:00', '2017-01-01 12:13:00', '2017-01-01 12:14:00', '2017-01-01 12:15:00'], 'val': [33, 42, 44, 6, 70, 94, 42, 97, 12, 11, 66, 71, 25, 23, 39, 25])
df.index = df.index*10
N = 3
idx = df['val'].rolling(window=N).sum()
i = np.nanargmax(idx) + 1
print(df.iloc[i-N : i])
打印
dt val
50 2017-01-01 12:05:00 94
60 2017-01-01 12:06:00 42
70 2017-01-01 12:07:00 97
iloc
uses ordinal indexing。 loc
使用基于标签的索引。前提是
i-N
和 i
都是有效索引,df.iloc[i-N : i]
将抓取一个窗口
(子DataFrame)长度N
。相比之下,df.loc[i-N, i]
只会抓取一个
如果索引使用连续整数,则窗口长度为N
。上面的例子
显示了一个 DataFrame,其中 df.loc
将无法工作,因为 df.index
有
非连续整数值。
【讨论】:
FWIW - 我无法让rolling()
使用我的时间戳 (ops for Rolling for this dtype datetime64[ns] are not implemented
) 或我的索引 ('Int64Index' object has no attribute 'rolling'
)。
rolling
不适用于datetime64
s,因为(例如)未定义求和datetime64
s。如果您希望在整数值索引上使用rolling
,可以使用df.index.to_series().rolling(...)
。【参考方案2】:
对于简单的单个值,您可以使用如下内容:
df['total'] = df.val + df.val.shift(-1) + df.val.shift(-2)
first = df.dropna().sort('total').index[-1]
df.iloc[first:first+3]
不知道如何概括这一点...对于大多数熊猫来说,可能有一种更简单的方法,但这确实有效。
编辑:经过更多的工作,看起来滚动就是你想要的:
last = df.val.rolling(3).sum().dropna().sort_values().index[-1]
这有点不同,因为你在这里得到的索引是end,所以做完上面你想做的事
df.iloc[last-2:last+1]
我认为这可以概括。
【讨论】:
好主意。在我想要 N=100 而不是 N=3 的情况下,有没有办法参数化第一行?【参考方案3】:您可以使用np.convolve
获取正确的起始索引并从那里开始。
def cons_max(df, N):
max_loc = np.convolve(df.val, np.ones(N, dtype=int), mode='valid').argmax()
return df.loc[max_loc:max_loc+N-1]
演示
>>> cons_max(df, 3)
dt val
5 2017-01-01 12:05:00 94
6 2017-01-01 12:06:00 42
7 2017-01-01 12:07:00 97
>>> cons_max(df, 5)
dt val
4 2017-01-01 12:04:00 70
5 2017-01-01 12:05:00 94
6 2017-01-01 12:06:00 42
7 2017-01-01 12:07:00 97
8 2017-01-01 12:08:00 12
这可以有效地在我们的输入中“滑动”内核(1 数组),并将大小为 N
的窗口中的元素相乘累加在一起。
【讨论】:
谢谢。这对于参数化N
非常有效
这实际上是一种非常有趣的方式...可以扩展很多方式...感谢您指出这一点!
如果 df.val 是浮点数而不是 int,必须 np.ones(3,dtype=float) 还是 int 仍然可以?
@philshem 是的,int
仍然可以 - 这些只是我们的乘数。
@CorleyBrigman 感谢一些食谱我不记得我从哪里了解到convolve
,但不客气!以上是关于Python Pandas - 查找具有最大聚合值的连续组的主要内容,如果未能解决你的问题,请参考以下文章
具有聚合唯一值的pyspark dataframe groupby [重复]
关于另一个 csv、pandas 上的操作(聚合最大值)的相应 csv 值
Pandas Dataframe groupby 聚合函数和动态列的最大值和最小值之间的差异