如何找到每个组的第一个本地最大值?

时间:2017-10-22 05:09:30

标签: python python-3.x pandas dataframe

假设我有一个Pandas数据框如下:

Test Parameter Value

X1     0        0.033285423511615113
X1     1        0.78790279861666179
X1     2        0.79136989638378297
X1     3        0.80063190842016707
X1     4        0.7884653622402551
X1     5        0.78561849214309198...
...
X1     22       22: 0.82241991278171311...
...
X2 ...

我希望得到参数值为3的行。这是第一次删除前最后一个增加值的行。请注意,稍后我们可能会有更高的值(例如第22行)。从本质上讲,我试图获得最后一次"在"第一"之前的数字减少价值。

另请注意,有多个测试,所以我可能需要执行以下操作:

myDF.groupby("Test").Something

5 个答案:

答案 0 :(得分:7)

Coldspeed几乎拥有它,只获得第一组你可以使用cumprod,或类似的。

In [11]: df[((df.Value.diff().fillna(1) > 0).cumprod()) == 1].tail(1)
Out[11]:
  Test  Parameter     Value
3   X1          3  0.800632

诀窍是:

In [12]: (df.Value.diff().fillna(1) > 0)
Out[12]:
0     True
1     True
2     True
3     True
4    False
5    False
6     True
Name: Value, dtype: bool

In [13]: (df.Value.diff().fillna(1) > 0).cumprod()
Out[13]:
0    1
1    1
2    1
3    1
4    0
5    0
6    0
Name: Value, dtype: int64

注意:我的df是这样的:

In [21]: df
Out[21]:
  Test  Parameter     Value
0   X1          0  0.033285
1   X1          1  0.787903
2   X1          2  0.791370
3   X1          3  0.800632
4   X1          4  0.788465
5   X1          5  0.785618
6   X1         22  0.822420

答案 1 :(得分:6)

使用np.diff,它会自然地将数组的长度减少一个,当我使用np.flatnonzero时,它将识别先前的序数位置。

df.iloc[[np.flatnonzero(np.diff(df.Value) < 0)[0]]]

  Test  Parameter     Value
3   X1          3  0.800632

注意:
我们可以通过访问底层的numpy数组来加快速度。

df.iloc[[np.flatnonzero(np.diff(df.Value.values) < 0)[0]]]

解释

获得差异

np.diff(df.Value)

array([ 0.754618,  0.003467,  0.009262, -0.012167, -0.002847,  0.036802])

找出差异为负的地方

np.flatnonzero(np.diff(df.Value) < 0)

array([3, 4])

我想要第一个

np.flatnonzero(np.diff(df.Value) < 0)[0]

3

iloc

中使用双括号
df.iloc[[3]]

  Test  Parameter     Value
3   X1          3  0.800632

该组看起来像

f = lambda d: d.iloc[[np.flatnonzero(np.diff(d.Value.values) < 0)[0]]]
df.groupby('Test').apply(f)

       Test  Parameter     Value
Test                            
X1   3   X1          3  0.800632

答案 2 :(得分:3)

使用diff + tail

df    
  Test  Parameter     Value
0   X1          0  0.033285
1   X1          1  0.787903
2   X1          2  0.791370
3   X1          3  0.800632
4   X1          4  0.788465
5   X1          5  0.785618

df[df.Value.diff().gt(0)].tail(1)    
  Test  Parameter     Value
3   X1          3  0.800632

这将检索最后本地最小值。如果您想要第一个本地最小值,请参阅Andy Hayden's solution涉及cumprod

如果您在groupby操作中执行此操作,则可能类似于(从Andy借用):

df.groupby('Test', group_keys=False)\
      .apply(lambda x: x[((x.Value.diff().fillna(1) > 0).cumprod()) == 1].tail(1))

答案 3 :(得分:3)

我认为max可以做到这一点......

df.sort_values('Value', ascending=False).drop_duplicates(['Test'])
Out[226]: 
  Test  Parameter     Value
3   X1          3  0.800632

df[df['Value'] == df.groupby(['Test'])['Value'].transform(max)]
Out[227]: 
  Test  Parameter     Value
3   X1          3  0.800632

似乎这就是你的需要......无论如何用丑陋的方式来纠正我的老帖子。

df1=df.loc[(df.Value.diff().fillna(1) > 0).nonzero()[0]].reset_index()
df1.groupby(df1['index'].diff().ne(1).cumsum()).last().iloc[0,]
Out[289]: 
index               3
Test               X1
Parameter           3
Value        0.800632
Name: 1, dtype: object

groupby

l=[]
for _,dfs in df.groupby('Test'):
    df1 = dfs.loc[(dfs.Value.diff().fillna(1) > 0).nonzero()[0]].reset_index()
    l.append(df1.groupby(df1['index'].diff().ne(1).cumsum()).last().iloc[0,].to_frame().T)


pd.concat(l,axis=0)

答案 4 :(得分:3)

同样来自scipy argrelextrema我们可以做(来自finding local maximas

from scipy.signal import argrelextrema
maxInd = argrelextrema(df['Value'].values, np.greater)
df.iloc[maxInd[0][:1]]
Test  Parameter     Value
3   X1          3  0.800632

如果您有数据框,则为groupby解决方案,即


 Test  Parameter     Value
0   X1          0  0.033285
1   X1          1  0.787903
2   X1          2  0.791370
3   X1          3  0.800632
4   X1          4  0.788465
5   X2          5  0.785618
6   X2         22  0.822420
7   X2          5  0.785618
def get_maxima(x):
    return x.iloc[argrelextrema(x['Value'].values,np.greater)[0][:1]]

df.groupby('Test').apply(get_maxima)

输出:

    Test  Parameter     Value
0 3   X1          3  0.800632
1 6   X2         22  0.822420