假设我有一个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
答案 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