如何通过数据框列中的正负数范围建立一个窗口?

问题描述 投票:0回答:1

我想在每一个正负值范围内都有平均值和最大值。

import pandas as pd
test_list = [-1, -2, -3, -2, -1, 1, 2, 3, 2, 1, -1, -4, -5, 2 ,4 ,7  ]
df_test = pd.DataFrame(test_list, columns=['value'])

给我的数据框是这样的。

    value
0      -1
1      -2
2      -3
3      -2
4      -1
5       1
6       2
7       3
8       2
9       1
10     -1
11     -4
12     -5
13      2
14      4
15      7

我想有这样的东西。

AVG1 = [-1, -2, -3, -2, -1] / 5 = - 1.8
Max1 = -3
AVG2 = [1, 2, 3, 2, 1] / 5 = 1.8 
Max2 = 3
AVG3 = [2 ,4 ,7] / 3 =  4.3
Max3 = 7

如果解决方案需要新的列或新的数据框架,那对我来说是可以的。

我知道我可以使用.mean,就像这里。pandas得到列平均数,并取整数。但是这个解决方案给我的是所有正值和负值的平均值。

如何建立某种窗口,使我可以从第一组负值计算平均值,然后从第二组正值计算平均值,等等。

谢谢

pandas pandas-groupby
1个回答
2
投票

你可以通过以下方法创建系列 np.sign 用于区分正负组,将移动值与各组的累计和进行比较,然后进行汇总。meanmax:

s = np.sign(df_test['value'])
g = s.ne(s.shift()).cumsum()
df = df_test.groupby(g)['value'].agg(['mean','max'])
print (df)
           mean  max
value               
1     -1.800000   -1
2      1.800000    3
3     -3.333333   -1
4      4.333333    7

EDIT:

为寻找地域极端值,使用了以下解决方案: 本回答:

test_list = [-1, -2, -3, -2, -1, 1, 2, 3, 2, 1, -1, -4, -5, 2 ,4 ,7  ]
df_test = pd.DataFrame(test_list, columns=['value'])

from scipy.signal import argrelextrema

#https://stackoverflow.com/a/50836425
n=2 # number of points to be checked before and after 
# Find local peaks
df_test['min'] = df_test.iloc[argrelextrema(df_test.value.values, np.less_equal, order=n)[0]]['value']
df_test['max'] = df_test.iloc[argrelextrema(df_test.value.values, np.greater_equal, order=n)[0]]['value']

然后将极端值替换为缺失值后的值,分别为负数组和正数组。

s = np.sign(df_test['value'])
g = s.ne(s.shift()).cumsum()

df_test[['min1','max1']] = df_test[['min','max']].notna().astype(int).iloc[::-1].groupby(g[::-1]).cumsum()
df_test['min1'] = df_test['min1'].where(s.eq(-1) & df_test['min1'].ne(0))
df_test['max1'] = df_test['max1'].where(s.eq(1) & df_test['max1'].ne(0))

df_test['g'] = g
print (df_test)
    value  min  max  min1  max1  g
0      -1  NaN -1.0   1.0   NaN  1
1      -2  NaN  NaN   1.0   NaN  1
2      -3 -3.0  NaN   1.0   NaN  1
3      -2  NaN  NaN   NaN   NaN  1
4      -1  NaN  NaN   NaN   NaN  1
5       1  NaN  NaN   NaN   1.0  2
6       2  NaN  NaN   NaN   1.0  2
7       3  NaN  3.0   NaN   1.0  2
8       2  NaN  NaN   NaN   NaN  2
9       1  NaN  NaN   NaN   NaN  2
10     -1  NaN  NaN   1.0   NaN  3
11     -4  NaN  NaN   1.0   NaN  3
12     -5 -5.0  NaN   1.0   NaN  3
13      2  NaN  NaN   NaN   1.0  4
14      4  NaN  NaN   NaN   1.0  4
15      7  NaN  7.0   NaN   1.0  4

因此,可以用lambda函数将每组的最后3个值分别汇总,然后再将这些值分别换成负值和正值。mean列表中缺少数值的行 min1max1 中默认删除。groupby:

df1 = df_test.groupby(['g','min1'])['value'].agg(lambda x: x.tail(3).mean())
print (df1)
g  min1
1  1.0    -2.000000
3  1.0    -3.333333
Name: value, dtype: float64

df2 = df_test.groupby(['g','max1'])['value'].agg(lambda x: x.tail(3).mean())
print (df2)
g  max1
2  1.0     2.000000
4  1.0     4.333333
Name: value, dtype: float64
© www.soinside.com 2019 - 2024. All rights reserved.