【问题标题】:Create multiple pandas DataFrame columns from applying a function with multiple returns通过应用具有多个返回的函数创建多个 pandas DataFrame 列
【发布时间】:2018-06-07 14:01:24
【问题描述】:

我想对pandas DataFrame 应用一个具有多个返回的函数,并将结果放在DataFrame 的单独新列中。

所以给定这样的东西:

import pandas as pd

df = pd.DataFrame(data = {'a': [1, 2, 3], 'b': [4, 5, 6]})

def add_subtract(a, b):
  return (a + b, a - b)

目标是在ab 上调用add_subtract 的单个命令,以在df 中创建两个新列:sumdifference

我认为这样的事情可能会奏效:

(df['sum'], df['difference']) = df.apply(
    lambda row: add_subtract(row['a'], row['b']), axis=1)

但它会产生这个错误:

----> 9 lambda 行:add_subtract(row['a'], row['b']), axis=1)

ValueError:解包的值太多(预计 2 个)

编辑:除以下答案外,pandas apply function that returns multiple values to rows in pandas dataframe 表明该函数可以修改为返回列表或Series,即:

def add_subtract_list(a, b):
  return [a + b, a - b]

df[['sum', 'difference']] = df.apply(
    lambda row: add_subtract_list(row['a'], row['b']), axis=1)

def add_subtract_series(a, b):
  return pd.Series((a + b, a - b))

df[['sum', 'difference']] = df.apply(
    lambda row: add_subtract_series(row['a'], row['b']), axis=1)

两者都有效(后者相当于 Wen 接受的答案)。

【问题讨论】:

    标签: python pandas


    【解决方案1】:

    添加pd.Series

    df[['sum', 'difference']] = df.apply(
        lambda row: pd.Series(add_subtract(row['a'], row['b'])), axis=1)
    df
    

    产量

       a  b  sum  difference
    0  1  4    5          -3
    1  2  5    7          -3
    2  3  6    9          -3
    

    【讨论】:

    • 谢谢!你能解释一下为什么这里需要pd.Series吗?
    • @MaxGhenis 您的函数中有元组,因此,我们将元组传递给 pd.Series ,这会将元组的列重建为两个 pd.Series (数据帧),更多信息stackoverflow.com/questions/29550414/…
    • 我想知道row['a']row['b'] 是否真的有效。通常这种引用不应该在apply()内部工作
    【解决方案2】:

    一种方法是使用pd.DataFrame.assign,如下所示:

    df.assign(**{k:v for k,v in zip(['sum', 'difference'], add_subtract(df.a, df.b))})
    

    应该让步:

       a  b  difference  sum
    0  1  4          -3    5
    1  2  5          -3    7
    2  3  6          -3    9
    

    说明:

    zip 是一个内置函数,它返回一个元组的迭代器,其中 i-th 元组 包含来自每个参数序列的 i-th 元素 或可迭代的。例如,list(zip(['sum', 'difference'], [df.a + df.b], df.a - df.b)) 应该返回 [('sum', df.a + df.b), ('difference', df.a - df.b)]

    ** 在字典对象前面用作解包 keyvalue 对组合的运算符。本质上,拆包可以表示为:sum=df.a + df.b, difference=df.a - df.b

    总而言之,当组合起来时,您会得到如下结果:

    df.assign(sum=df.a + df.b, difference=df.a - df.b)
    

    按照提供的链接指向字典对象前面的zip** 运算符,以更好地了解这些有用的工具在这个特定示例之外是如何工作的。

    【讨论】:

    • 这很有趣:我对 Python 比较陌生(主要是 R 用户),所以你能解释一下 **zip 在这里做什么吗?似乎是一个有用的构造。我接受了 Wen 的回答,因为它与我的猜测差异最小,但对此表示赞同,如果这在性能方面会显着提高,则可以更改。
    • @MaxGhenis 您可以将 python 中的 zip 视为 R 中的列表列表,在 R 中我们需要 unlist 这是 R 的示例 :-) (PS,我也是 50% R 用户:-) ) stackoverflow.com/questions/4227223/r-list-to-data-frame
    • 那句话有点欠缺。 R 中的数据结构在 python 数据结构中并不容易翻译。我在 R 中能想到的最接近 zip 的是 purrr 包中的 transpose 函数。即便如此,在所有情况下的工作方式都不尽相同。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-07-02
    • 2018-01-01
    • 2021-03-16
    • 1970-01-01
    • 2016-01-07
    • 2013-11-23
    • 1970-01-01
    相关资源
    最近更新 更多