Groupby 名称用所有列中的最大值替换值 pandas

Posted

技术标签:

【中文标题】Groupby 名称用所有列中的最大值替换值 pandas【英文标题】:Groupby names replace values with there max value in all columns pandas 【发布时间】:2020-12-03 14:42:15 【问题描述】:

我有这个数据框

lst = [['AAA',15,'BBB',20],['BBB',16,'AAA',12],['BBB',22,'CCC',15],['CCC',11,'AAA',31],['DDD',25,'EEE',35]]
df = pd.DataFrame(lst,columns = ['name1','val1','name2','val2'])

看起来像这样

 name1   val1 name2 val2
0  AAA     15  BBB   20
1  BBB     16  AAA   12
2  BBB     22  CCC   15
3  CCC     11  AAA   31
4  DDD     25  EEE   35

我想要这个

 name1   val1 name2  val2
0  AAA     31  BBB    22
1  BBB     22  AAA    31
2  BBB     22  CCC    15
3  CCC     15  AAA    31
4  DDD     25  EEE    35

用最大值替换所有值。我们从val1val2中选择最大值

如果我这样做,我将只从 val1 获得最大值

df["val1"] = df.groupby("name1")["val1"].transform("max")

【问题讨论】:

name2 不应该是字符串而不是数字吗? 您的 BBB 输入的 val2 为 12 和 15 - 为什么您的输出有 31 和 15? @HenryYik 我的错误编辑了它 为什么有 2 组列(name1name2val1val2)?为什么不能有一个 name 列和一个 val 列,有充分的理由吗? @JonClements BBB val1 和 val2 的最大值为 22,因此将所有 BBB 替换为 22 【参考方案1】:

这是基于@ScottBoston 的回答:

res = pd.wide_to_long(df.reset_index(), ["name", "val"], "index", j="num")
res.update(res.groupby(["name"]).val.transform("max"))
res = res.unstack()
res.columns = [f"firstlast" for first, last in res.columns]
res.rename_axis(index=None)


   name1    name2   val1    val2
0   AAA     BBB     31      22
1   BBB     AAA     22      31
2   BBB     CCC     22      15
3   CCC     AAA     15      31
4   DDD     EEE     25      35

【讨论】:

【参考方案2】:

您可以使用lreshape(未记录且不确定是否已测试或将继续保留)获取长数据帧,然后使用最大值映射每对列。

names = df.columns[df.columns.str.startswith('name')]
vals = df.columns[df.columns.str.startswith('val')]

s = (pd.lreshape(df, groups='name': names, 'val': vals)
       .groupby('name')['val'].max())

for n in names:
    df[n.replace('name', 'val')] = df[n].map(s)

  name1  val1 name2  val2
0   AAA    31   BBB    22
1   BBB    22   AAA    31
2   BBB    22   CCC    15
3   CCC    15   AAA    31
4   DDD    25   EEE    35

【讨论】:

【参考方案3】:

借用 Scott 的设置

df_long = pd.wide_to_long(df.reset_index(), ['name','val'], 'index', j='num',sep='',suffix='\d+')
d = df_long.groupby('name')['val'].max()

df.loc[:,df.columns.str.startswith('val')]=df.loc[:,df.columns.str.startswith('name')].replace(d).values
df
Out[196]: 
  name1  val1 name2  val2
0   AAA    31   BBB    22
1   BBB    22   AAA    31
2   BBB    22   CCC    15
3   CCC    15   AAA    31
4   DDD    25   EEE    35

【讨论】:

【参考方案4】:

尝试使用pd.wide_to_long 将该数据框融合成一个长格式,然后使用 groupby 和 transform 来找到最大值。将该最大值映射到“名称”并重新整形为四列(宽)数据框:

df_long = pd.wide_to_long(df.reset_index(), ['name','val'], 'index', j='num',sep='',suffix='\d+')
mapper= df_long.groupby('name')['val'].max()
df_long['val'] = df_long['name'].map(mapper)
df_new = df_long.unstack()
df_new.columns = [f'ij' for i,j in df_new.columns]
df_new

输出:

      name1 name2  val1  val2
index                        
0       AAA   BBB    31    22
1       BBB   AAA    22    31
2       BBB   CCC    22    15
3       CCC   AAA    15    31
4       DDD   EEE    25    35

【讨论】:

以上是关于Groupby 名称用所有列中的最大值替换值 pandas的主要内容,如果未能解决你的问题,请参考以下文章

Python pandas:替换 groupby 对象中的选择值

7.02 求某列中的最小最大值

replace函数对dataframe中的值进行替换(所有数据列中的相同值)

groupby 基于一列并获取另一列中的总和值

Pandas DataFrame:根据条件替换列中的所有值

根据熊猫中多列的条件(最大值)替换列中的值