【问题标题】:How to add multiple columns to a DataFrame?如何将多个列添加到 DataFrame?
【发布时间】:2018-02-27 19:24:13
【问题描述】:

我想向这个 DataFrame 添加总字段:

df_test = pd.DataFrame([
    {'id':1,'cat1a':3,'cat1b':2, 'cat2a':4,'cat2b':3},
    {'id':2,'cat1a':7,'cat1b':5, 'cat2a':9,'cat2b':6}
])

这段代码几乎可以工作:

 def add_total(therecord):
        t1 = therecord['cat1a'] + therecord['cat1b']
        t2 = therecord['cat2a'] + therecord['cat2b']
        return t1, t2

df_test['cat1tot', 'cat2tot'] = df_test[['cat1a', 'cat1b', 'cat2a', 'cat2b']].apply(add_total,axis=1)

除非它只产生 1 个新列:

还有这段代码:

 def add_total(therecord):
        t1 = therecord['cat1a'] + therecord['cat1b']
        t2 = therecord['cat2a'] + therecord['cat2b']
        return [t1, t2]

df_test[['cat1tot', 'cat2tot']] = df_test[['cat1a', 'cat1b', 'cat2a', 'cat2b']].apply(add_total,axis=1)

结果:KeyError: "['cat1tot' 'cat2tot'] not in index"

我试图解决这个问题:

my_cols_list=['cat1tot','cat2tot']
df_test.reindex(columns=[*df_test.columns.tolist(), *my_cols_list], fill_value=0)

但这并没有解决问题。那我错过了什么?

【问题讨论】:

  • 您是否尝试过.withColumn(),可能使用.drop() 来删除不需要的源列?还是df_test.select((df_test.cat1a + df_test.cat1b).alias("cat1tot"))等?
  • @9000 这些对我来说看起来不像是有效的 pandas 函数......你运行的是什么版本?
  • @BradRhoads,您是否只想添加无法矢量化的总数或更复杂的计算?
  • @cᴏʟᴅsᴘᴇᴇᴅ:啊,把 Pandas DataFrame 误认为 Spark DataFrame!因此混乱。确实,这不适用于 Pandas。

标签: python pandas dataframe


【解决方案1】:

除非绝对必须,否则使用df.apply 通常不是一个好主意。原因是这些操作没有向量化,即在后台有一个循环,其中每一行都作为自己的pd.Series 输入到一个函数中。

这将是一个矢量化的实现:

df_test['cat1tot'] = df_test['cat1a'] + df_test['cat1b']
df_test['cat2tot'] = df_test['cat2a'] + df_test['cat2b']

#    cat1a  cat1b  cat2a  cat2b  id  cat1tot  cat2tot
# 0      3      2      4      3   1        5        7
# 1      7      5      9      6   2       12       15

【讨论】:

  • 我假设这是一个玩具示例,否则这将是我的下意识反应 ;)
  • @COLDSPEED,我还不知道。如果事实证明用户想要执行更复杂的不可并行操作,我会很乐意删除这个答案:)
  • 我对 python 还很陌生。你能再解释一下吗? 似乎您的解决方案需要循环遍历数据集两次而不是一次。是的,这是一个玩具示例。真实数据有10组7列,所以需要添加tot1、tot2、. . ., tot10.
  • 当然,很乐意解释。看起来您正在做“2 行工作”,但 2 行应该比单个 df.apply 快得多。在后台,有针对+、* 等简单计算的高度优化的基于numpy 的计算[高效库],这意味着计算不会一次循环遍历一行。另见:Pandas - Explanation on apply function being slow
  • @BradRhoads 这种方法将明显比任何涉及 .apply 的方法都要快。
【解决方案2】:

改为返回Series 对象:

def add_total(therecord):
    t1 = therecord['cat1a'] + therecord['cat1b']
    t2 = therecord['cat2a'] + therecord['cat2b']

    return pd.Series([t1, t2])

然后,

df_test[['cat1tot', 'cat2tot']] = \
      df_test[['cat1a', 'cat1b', 'cat2a', 'cat2b']].apply(add_total,axis=1)

df_test

   cat1a  cat1b  cat2a  cat2b  id  cat1tot  cat2tot
0      3      2      4      3   1        5        7
1      7      5      9      6   2       12       15

这行得通,因为apply 将特殊情况下Series 返回类型,并假设您希望将结果作为数据帧切片。

【讨论】:

  • 这很有效,并且最接近我想要做的。
【解决方案3】:

怎么样

df_test['cat1tot'], df_test['cat2tot'] =\
   df_test[['cat1a', 'cat1b', 'cat2a', 'cat2b']].apply(add_total,axis=1)

【讨论】:

    猜你喜欢
    • 2016-11-08
    • 2016-05-03
    • 1970-01-01
    • 2021-06-26
    • 2015-10-15
    • 1970-01-01
    • 1970-01-01
    • 2022-01-23
    • 1970-01-01
    相关资源
    最近更新 更多