【问题标题】:Why use pandas.assign rather than simply initialize new column?为什么使用 pandas.assign 而不是简单地初始化新列?
【发布时间】:2022-03-19 11:06:55
【问题描述】:

我刚刚发现了用于 pandas 数据帧的 assign 方法,它看起来不错,并且与 R 中 dplyr 的 mutate 非常相似。但是,我总是通过“即时”初始化一个新列来解决问题。 assign 更好有什么原因吗?

例如(基于 pandas 文档中的示例),要在数据框中创建一个新列,我可以这样做:

df = DataFrame({'A': range(1, 11), 'B': np.random.randn(10)})
df['ln_A'] = np.log(df['A'])

pandas.DataFrame.assign 文档建议这样做:

df.assign(ln_A = lambda x: np.log(x.A))
# or 
newcol = np.log(df['A'])
df.assign(ln_A=newcol)

两种方法都返回相同的数据帧。事实上,第一种方法(我的“即时”分配)比.assign 方法(0.353 秒,1000 次迭代)快得多(0.202 秒,1000 次迭代)。

那么我是否有理由停止使用我的旧方法来支持df.assign

【问题讨论】:

  • 我认为这是风格问题
  • 嗯,我知道的唯一原因是它允许方法链接。你可以做类似df.assign(some_col=some_exp).some_other_method_involving_the_new_column()
  • This issue 也支持它主要用于方法链。
  • 它们在语义上是不同的。一个是就地修改,另一个不是。
  • 旧版本 df['ln_A'] = np.log(df['A']) 现在可以提高 SettingWithCopyWarning

标签: python pandas


【解决方案1】:

区别在于您是希望修改现有框架,还是创建新框架同时保持原始框架不变。

特别是,DataFrame.assign 会返回一个 new 对象,该对象具有原始数据的副本以及请求的更改...原始框架保持不变

在您的特定情况下:

>>> df = DataFrame({'A': range(1, 11), 'B': np.random.randn(10)})

现在假设您希望创建一个新框架,其中A 无处不在1 而不会破坏df。然后你可以使用.assign

>>> new_df = df.assign(A=1)

如果您不想保持原始值,那么显然df["A"] = 1 会更合适。这也解释了速度差异,.assign 必须复制数据,而[...] 不需要。

【讨论】:

    【解决方案2】:

    assign的前提是它返回:

    除了所有现有列之外,还包含新列的新 DataFrame。

    而且你也不能在原地做任何事情来改变原始数据框。

    callable 不能更改输入 DataFrame(尽管 pandas 不会检查它)。

    另一方面,df['ln_A'] = np.log(df['A']) 会就地做事。


    那么我是否有理由停止使用我的旧方法来支持df.assign

    我认为您可以尝试df.assign,但如果您进行内存密集型工作,最好使用您之前所做的工作或使用inplace=True 进行操作。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-11-10
      • 1970-01-01
      • 2013-12-16
      相关资源
      最近更新 更多