在带有 Groupby 的 Pandas 中:从以另一列为条件的列中分配一个值

Posted

技术标签:

【中文标题】在带有 Groupby 的 Pandas 中:从以另一列为条件的列中分配一个值【英文标题】:In Pandas with Groupby: assign a value from a column conditioned on another column 【发布时间】:2021-09-02 13:19:01 【问题描述】:

我有一个这样的 DataFrame:

df = pd.DataFrame('col0': list('aabb'), 
                   'col1': np.arange(4),
                   'col2': list('wxyz'),
                   'col3': np.nan)

    col0 col1 col2 col3
0   a    0    w    NaN
1   a    1    x    NaN
2   b    2    y    NaN
3   b    3    z    NaN

我想将“col1”的最小值对应的“col2”的值分配给“col3”,按“col0”分组。预期输出:

    col0 col1 col2 col3
0   a    0    w    w
1   a    1    x    w
2   b    2    y    y
3   b    3    z    y

如果不需要按 'col0' 分组,这会起作用:

df['col3'] = df[df['col1']==df['col1'].min()]['col2'].iloc[0]

    col0 col1 col2 col3
0   a    0    w    w
1   a    1    x    w
2   b    2    y    w
3   b    3    z    w

同样,这是我使用 groupby/apply 的尝试,但没有按预期工作:

df['col3'] = df.groupby('col0').apply(lambda x: x[x['col1']==x['col1'].min()]['col2'].iloc[0])

    col0 col1 col2 col3
0   a    0    w    NaN
1   a    1    x    NaN
2   b    2    y    NaN
3   b    3    z    NaN

【问题讨论】:

【参考方案1】:

你可以通过变换idxmin然后series.map进行分组:

d = dict(zip(df['col1'],df['col2']))
df['col3'] = df['col3'].fillna(df.groupby("col0")['col1'].transform('idxmin').map(d))

print(df)

  col0  col1 col2 col3
0    a     0    w    w
1    a     1    x    w
2    b     2    y    y
3    b     3    z    y    

【讨论】:

【参考方案2】:

另一个transforming 与idxminloc

df["col3"] = df.groupby("col0").col1.transform(lambda x: df.loc[x.idxmin(), "col2"])

得到

  col0  col1 col2 col3
0    a     0    w    w
1    a     1    x    w
2    b     2    y    y
3    b     3    z    y

【讨论】:

好吧,我的是最差的,你的是最好的:) @Stryder 我强烈反对:) 这非常适用于我在 col1 中寻找最小值索引的特殊情况。如果我有一个更一般的条件:“将与 'col1' 的 真实条件 对应的 'col2' 的值分配给 'col3',按 'col0' 分组”怎么办? @makpalan 我不确定你所说的真实条件是什么意思,但也许它也可以放在上面的loc 中而不是idxmin。您能否详细说明情况以及一些示例输入/输出(通过编辑问题)?如果这会使当前的问题变得非常不同,那么您可能会选择问另一个问题,但如果它足够接近,也许没问题,谢谢。 @MustafaAydın 说我想要 col3 的 col2 的(第一个)值,其中 col1>0(与最小值不同的条件,即使在这里微不足道),然后我发现了这个:df["col3"] = df.groupby("col0").col1.transform(lambda x: df.loc[x.index[x>0].tolist()[0], 'col2'])。按照您的方法实际上可以得到更通用的东西,这实际上是我正在寻找的,谢谢【参考方案3】:

您可以使用 groupby.apply 获取一个系列,然后将其合并到 df 中

df
  col0  col1 col2
0    a     0    w
1    a     1    x
2    b     2    y
3    b     3    z

col3 = df.groupby("col0").apply(lambda x: x.loc[x["col1"].idxmin(), "col2"])
col3.name = "col3"
df = df.merge(col3, how="left", left_on= "col0", right_index= True)

df
 col0  col1 col2 col3
0    a     0    w    w
1    a     1    x    w
2    b     2    y    y
3    b     3    z    y

【讨论】:

以上是关于在带有 Groupby 的 Pandas 中:从以另一列为条件的列中分配一个值的主要内容,如果未能解决你的问题,请参考以下文章

带有最小值、最大值和总和的 Pandas 数据框 Groupby

Python Pandas - 带有 apply() 和 rolling() 的 groupby() 非常慢

带有 MultiIndexing 的 Pandas 数据框中的 Groupby

使用带有参数的 Pandas groupby() + apply()

带有分隔符的 Pandas groupby 连接

带有冗余 nan 类别的 Pandas groupby