【问题标题】:Groupby and perform row-wise calculation using a custom functionGroupby 并使用自定义函数执行逐行计算
【发布时间】:2017-09-27 15:04:03
【问题描述】:

接着这个问题:python - Group by and add new row which is calculation of other rows

我有一个熊猫数据框如下:

col_1   col_2   col_3  col_4
a       X        5      1
a       Y        3      2
a       Z        6      4
b       X        7      8
b       Y        4      3
b       Z        6      5

我想对 col_1 中的每个值应用一个函数,其中 col_3 和 col_4(以及更多列)中的值对应于 col_2 中的 X 和 Z,并使用这些值创建一个新行。所以输出如下:

col_1   col_2   col_3  col_4 
a       X        5      1
a       Y        3      2
a       Z        6      4
a       NEW      *      *
b       X        7      8
b       Y        4      3
b       Z        6      5
b       NEW      *      *

* 是函数的输出。

原始问题(只需要简单添加)的回答是:

new = df[df.col_2.isin(['X', 'Z'])]\
  .groupby(['col_1'], as_index=False).sum()\
  .assign(col_2='NEW')

df = pd.concat([df, new]).sort_values('col_1')

我现在正在寻找一种使用自定义函数的方法,例如(X/Y)((X+Y)*2),而不是X+Y。如何修改此代码以适应我的新要求?

【问题讨论】:

  • 在看到coldspeed的答案之前,我已经找到了您正在寻找的解决方案。
  • 不是重复的@zipa,它是该问题的后续。回答了这个问题的 Coldspeed 建议创建一个新问题以增加难度。
  • @Saturate 为清楚起见修改了您的问题。
  • 答案很长,所以很高兴您提出了后续问题。 :-)

标签: python pandas dataframe group-by pandas-groupby


【解决方案1】:

我不确定这是否是您正在寻找的,但这里是:

def f(x):
    y = x.values
    return y[0] / y[1] # replace with your function

而且,对new 的更改是:

new = (
    df[df.col_2.isin(['X', 'Z'])]
      .groupby(['col_1'], as_index=False)[['col_3', 'col_4']]
      .agg(f)
      .assign(col_2='NEW')
)

  col_1     col_3  col_4 col_2
0     a  0.833333   0.25   NEW
1     b  1.166667   1.60   NEW

df = pd.concat([df, new]).sort_values('col_1')

df
  col_1 col_2     col_3  col_4
0     a     X  5.000000   1.00
1     a     Y  3.000000   2.00
2     a     Z  6.000000   4.00
0     a   NEW  0.833333   0.25
3     b     X  7.000000   8.00
4     b     Y  4.000000   3.00
5     b     Z  6.000000   5.00
1     b   NEW  1.166667   1.60

我对@9​​87654324@ 充满信心,并假设这些列在到达函数之前已排序。如果不是这种情况,则需要额外的sort_values 调用:

df = df.sort_values(['col_1, 'col_2'])

应该做的伎俩。

【讨论】:

  • 这很棒。 ;我知道你会想出这个的。
  • @Bharathshetty 是的..您的原始答案还可以,但没有解决 OP 的新要求 :-)
  • 现在你知道为什么它被删除了哈哈。
  • 谢谢@cᴏʟᴅsᴘᴇᴇᴅ,又很棒了!我只需要将 ['col_3', 'col_4'] 部分更改为除 col_1 和 col_2 之外的所有列的列表,因为要计算的列数每次都可能发生变化,但我可以处理。无论如何,现在一切正常,干杯。
  • @Saturate 用[df.columns.difference(['col_1, 'col_2'])] 代替['col_3', 'col_4', xxxxxxx, yyyyyy, zzzzz, aaaa, bbb, ccc, ddd, eee, ....] 应该更容易。干杯。
【解决方案2】:
def foo(df):
    # Expand variables into dictionary.
    d = {v: df.loc[df['col_2'] == v, ['col_3', 'col_4']] for v in df['col_2'].unique()}

    # Example function: (X + Y ) * 2
    result = (d['X'].values + d['Y'].values) * 2

    # Convert result to a new dataframe row.
    result = result.tolist()[0]
    df_new = pd.DataFrame(
        {'col_1': [df['col_1'].iat[0]], 
         'col_2': ['NEW'], 
         'col_3': result[0],
         'col_4': result[1]})
    # Concatenate result with original dataframe for group and return.
    return pd.concat([df, df_new])

>>> df.groupby('col_1').apply(lambda x: foo(x)).reset_index(drop=True)
  col_1 col_2  col_3  col_4
0     a     X      5      1
1     a     Y      3      2
2     a     Z      6      4
3     a   NEW     16      6
4     b     X      7      8
5     b     Y      4      3
6     b     Z      6      5
7     b   NEW     22     22

【讨论】:

    【解决方案3】:

    一种较新的方法(应该提供性能优势)是使用 PyArrow 和 pandas_udf 来支持矢量化操作,如 Spark 2.4 中所述:PySpark Usage Guide for Pandas with Apache Arrow

    【讨论】:

      猜你喜欢
      • 2018-10-19
      • 1970-01-01
      • 2017-11-30
      • 2021-05-08
      • 1970-01-01
      • 1970-01-01
      • 2019-02-18
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多