我正在寻找一种在Pandas中执行滚动功能的方法,并保留一个特定值,例如最高或最低值,然后删除与该范围相交的所有其他窗口。
想象一下,例如一年的温度测量,你想知道已经发生的最温暖的20天。绝对最温暖很容易,执行滚动功能并对结果进行排序。但考虑到温度如何变化的性质,第二个,第三个等可能是同一个时期,窗口只有一天的变化。这就是我想要避免的,因此最终只能得到独特的,不相交的句号。
我找到了下面列出的一个解决方法,但它涉及循环,将结果存储在列表中并重新创建DataFrame,这远非花哨。所以我很好奇是否有人知道处理这些情况的更多Pythonic方式。
可以使用以下内容创建示例数据:
window = 20
end = pd.DatetimeIndex(start='2014-01-01', end='2014-12-31', freq='D')
begin = end.shift(-(window - 1))
df = pd.DataFrame({'begin': begin,
'end': end,
'values': np.sin(np.linspace(-np.pi, np.pi, len(begin))) * 10.})
df['values'] = pd.rolling_mean(df['values'], window)
df = df.dropna()
这给出了一年的虚拟数据减去由于窗口中缺少值而丢失的前19天。
我的方法如下:
# sort the DataFrame so the 'to keep' values are at the beginning, in this case highest
# 'values' first. But an alternative way of ordering could be used of course.
df.sort('values', ascending=False, inplace=True)
# a list to store rows
keep = []
# loop until there are no rows left in the DataFrame
while len(df) > 0:
# select the top row
toprow = df.iloc[0]
# store it
keep.append(toprow)
# get the range of the tow
end = toprow.end
begin = toprow.begin
# boolean mask for all ranges intersecting the selected range
before = (df.end >= begin) & (df.end <= end)
after = (df.begin >= begin) & (df.begin <= end)
# remove all other values intersecting with the range
df = df[~(before | after)]
# merge the stored rows (Series) to a DataFrame
df = pd.concat(keep, axis=1).T
df.set_index(['begin', 'end'], inplace=True)
df.head()
结果是:
values
begin end
2014-09-21 2014-10-10 9.950167
2014-10-11 2014-10-30 9.392147
2014-09-01 2014-09-20 9.334021
2014-10-31 2014-11-19 7.725809
2014-08-12 2014-08-31 7.616417
因为我使用正弦作为虚拟数据,所以第二高的窗口就在最高的旁边,等等。
不,这应该适用于熊猫吗?它导致了我的错误:del df[~(before | after)]