繁体   English   中英

根据多行分组条件更改 pandas 列中的单元格值

[英]Changing a cell value in pandas column based on multiple rows grouping condition

我有一个 pandas dataframe 包含三列:

import pandas as pd
di={'id':[1,1,2,3,4,4],'b':['Sydney','Bexley','Arncliffe','Hurstville','Bexley North','Carlton'],
   'c':['contra','contra','contra_approved','contra','contra_approved','contra']}

df=pd.DataFrame(di)
df.head(10)


id  b             c
1   Sydney        contra
1   Bexley        contra
2   Arncliffe     contra_approved
3   Hurstville    contra
4   Bexley North  contra_approved
4   Carlton       contra

每个id都应该在'c'列中有一个关键字contra_approved

  • 对于带有关键字' contra '的一个值的 id,我需要更改为contra_approved (例如 id 3
  • 对于具有关键字 contra 且其中没有任何一个为contra_approved的多行 id,我需要将id相关行中的第一次出现更改为contra_approved (例如 id 1 )。

最终的 dataframe 将是:


id  b             c
1   Sydney        contra_approved
1   Bexley        contra
2   Arncliffe     contra_approved
3   Hurstville    contra_approved
4   Bexley North  contra_approved
4   Carlton       contra

如何解释 pandas 中的以下逻辑?

我们试试看:

# check if all rows within same `id` have `c==contra`
g = df['c'].eq('contra').groupby(df['id']).transform('all')

# switch the first of those group into `contra_approved` 
# regardless of counts
df.loc[g & (~df.duplicated('id')), 'c'] = 'contra_approved'

Output:

   id             b                c
0   1        Sydney  contra_approved
1   1        Bexley           contra
2   2     Arncliffe  contra_approved
3   3    Hurstville  contra_approved
4   4  Bexley North  contra_approved
5   4       Carlton           contra

你可以试试:

def f(d):
    if "contra_approved" not in d["c"].unique():
        d.loc[d.index[0], "c"] = "contra_approved"
    return d

df = df.groupby("id").apply(f)
g=df.groupby('id').head(1)
df[~df.isin(g)].dropna().append(g.replace(regex='^contra$',value='contra_approved')).sort_values(by='id')


   id             b                c
1  1.0        Bexley           contra
0  1.0        Sydney  contra_approved
2  2.0     Arncliffe  contra_approved
3  3.0    Hurstville  contra_approved
5  4.0       Carlton           contra
4  4.0  Bexley North  contra_approved

这个怎么运作

  1. g=df.groupby('id').head(1) #隔离每组的第一个

  2. g.replace(regex='^contra$',value='contra_approved') #replace contra in g

  3. df[~df.isin(g)] #隔离每组中不在第一个的

  4. 结合第二步和第三步的结果

让我们试试

cond = df.groupby('id').cumcount().eq(0) 
       & ~df.id.isin(df.loc[df.c.eq('contra_approved'),'id'])
df.loc[cond,'c']='contra_approved'
df
Out[146]: 
   id             b                c
0   1        Sydney  contra_approved
1   1        Bexley           contra
2   2     Arncliffe  contra_approved
3   3    Hurstville  contra_approved
4   4  Bexley North  contra_approved
5   4       Carlton           contra

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM