pandas 选择数据框中的行满足多列中的unill条件

atmip9wb  于 2023-04-18  发布在  其他
关注(0)|答案(6)|浏览(172)

我有一个数据框df = pd.DataFrame({'id': [1, 1, 1, 1, 1, 2, 2, 2, 2, 2], 'value2': [30, 28, 27, 24, 25, 29, 28, 28, 26, 25], 'value3': [29, 29, 27, 25, 24, 27, 27, 26, 26, 26], 'value4': [30, 29, 25, 25, 25, 29, 28, 28, 25, 26]})
| 身份证|价值观2|价值观3|价值观4|
| --------------|--------------|--------------|--------------|
| 1|三十|二十九|三十|
| 1|二十八|二十九|二十九|
| 1|二十七|二十七|二十五|
| 1|二十四|二十五|二十五|
| 1|二十五|二十四|二十五|
| 二|二十九|二十七|二十九|
| 二|二十八|二十七|二十八|
| 二|二十八|二十六|二十八|
| 二|二十六|二十六|二十五|
| 二|二十五|二十六|二十六|
并且我需要选择每个id中的所有行,直到列value2value3value4满足条件。条件如下:选择每个组中的所有行(id),直到任何列(value2value3value4)中的值小于或等于25。所以我的最终表应该是这样的:
| 身份证|价值观2|价值观3|价值观4|
| --------------|--------------|--------------|--------------|
| 1|三十|二十九|三十|
| 1|二十八|二十九|二十九|
| 1|二十七|二十七|二十五|
| 二|二十九|二十七|二十九|
| 二|二十八|二十七|二十八|
| 二|二十八|二十六|二十八|
| 二|二十六|二十六|二十五|
我试过df[df['value2'].eq(25).cummin() | df['value3'].eq(25).cummin() | df['value4'].eq(25).cummin()],但它是严格的25,而不是小于或等于25,并只适用于整个datafame(而不是每个id)。什么是最好的方式来过滤datafame根据我的条件?

vsmadaxz

vsmadaxz1#

您可以将自定义groupby.applycummaxanyshift一起使用:

m = (
 df.filter(like='value').le(25).any(axis=1)
   .groupby(df['id'], group_keys=False)
   .apply(lambda g: ~g.cummax().shift(fill_value=False))
)

out = df[m]

输出:

id  value2  value3  value4
0   1      30      29      30
1   1      28      29      29
2   1      27      27      25
5   2      29      27      29
6   2      28      27      28
7   2      28      26      28
8   2      26      26      25
kulphzqa

kulphzqa2#

等价于value2 > 25 and value3 > 25 and value4 >= 25,所以一个非常快速的布尔掩码解决方案:

df[(df['value2'].gt(25) & df['value3'].gt(25) & df['value4'].ge(25))]
id  value2  value3  value4
0   1      30      29      30
1   1      28      29      29
2   1      27      27      25
5   2      29      27      29
6   2      28      27      28
7   2      28      26      28
8   2      26      26      25
v440hwme

v440hwme3#

不知道这是否是最短的方法,但根据您的各种条件,认为这将为您提供所需的...... df是您现有的 Dataframe ,df1将是您过滤的 Dataframe 。

df = pd.DataFrame({'id': [1, 1, 1, 1, 1, 2, 2, 2, 2, 2], 'value2': [30, 28, 27, 24, 25, 29, 28, 28, 26, 25], 'value3': [29, 29, 27, 25, 24, 27, 27, 26, 26, 26], 'value4': [30, 29, 25, 25, 25, 29, 28, 28, 25, 26]})

df1=pd.DataFrame()
for ID in df.id.unique(): ##For each ID
    for _, row in df[df.id==ID].iterrows(): ## For each row
        df1=df1.append(row)  ## First append
        if row.value4 <= 25 or row.value2 <= 25 or row.value3 <= 25:
            break ## Check if 25 or below exists and if yes, exit
w6lpcovy

w6lpcovy4#

另一种方法是使用idxminidxmax

cols = df.drop('id',axis=1).columns
g = df.assign(t=df[cols].le(25).any(axis=1)).groupby('id')
m = g['t'].idxmax()
f = g['t'].idxmin()
out = pd.concat([df.iloc[s:e+1] for s, e in zip(f.values, m.values)])
print(out)

   id  value2  value3  value4
0   1      30      29      30
1   1      28      29      29
2   1      27      27      25
5   2      29      27      29
6   2      28      27      28
7   2      28      26      28
8   2      26      26      25
5w9g7ksd

5w9g7ksd5#

我将创建一个临时列来存储值1,如果跨行的值〈= 25。然后我将使用cumsum函数:

df['minval']= np.where(df[['value2','value2','value3']].min(axis=1)<=25,1,0)

df['minval']= df.groupby('id')['minval'].cumsum()

df[df.minval<=1].drop(columns='minval')
lyr7nygr

lyr7nygr6#

下面是使用.transform('idxmax')的方法

df.loc[df.index<=df[['value2','value3','value4']].le(25).any(axis=1).groupby(df['id']).transform('idxmax')]

输出:

id  value2  value3  value4
0   1      30      29      30
1   1      28      29      29
2   1      27      27      25
5   2      29      27      29
6   2      28      27      28
7   2      28      26      28
8   2      26      26      25

相关问题