apply + list comprehension在返回列表长度与数据帧列数相同时给出ValueError

时间:2017-11-17 23:33:08

标签: python pandas

这个问题源于this comment thread。使用Pandas 0.20.3

我试图理解为什么apply()操作会抛出错误:

  

ValueError:传递的项目数量错误2,展示位置意味着1

Pandas ValueError的这种特殊风格是not uncommon,但它通常来自一个更明显的尝试,将一堆元素塞进一个专为较小的设计的数据结构中容量。同样的事情必须在这里进行,但我无法弄清楚原因。

给定一个包含整数AB列的数据框:

import pandas as pd

df = pd.DataFrame({'A': [1,2], 'B': [3,4]})
df
   A  B
0  1  3
1  2  4

我可以构建一个新列C,这是一列列表 C中的每个列表都包含AB的值 C应如下所示:

     C
[1, 3]
[2, 4]

我选择使用C和列表理解来构建apply()

df['C'] = df.apply(lambda x: [val for val in x], axis=1)

(现在,请忽略这可能不是实现这一目标的最优雅方式 - 它主要是一种解决我感到困惑的错误的途径。)

这会抛出上面提到的ValueError ,我可以毫不费力地为每行创建更多项目的列表:

df['C'] = df.apply(lambda x: [val for val in x]+[1], axis=1)
df
   A  B          C
0  1  3  [1, 3, 1]
1  2  4  [2, 4, 1]

我原以为我会得到同样的错误,只有Wrong number of items passed 3...代替2

我还可以使用更少的项目创建C

df['C'] = df.apply(lambda x: [val for val in x][:1], axis=1)
df
   A  B    C
0  1  3  [1]
1  2  4  [2]

此外,C在第一行的列表长度短于或长于[1,3]时生成,但在第一行的列表长度与len([1,3])匹配时失败,即使后续列表长度不同:

df['C'] = df.apply(lambda x: [val for val in x if val != 1], axis=1) # this works
df['C'] = df.apply(lambda x: [val for val in x if val != 4], axis=1) # this fails

鉴于所有这些不同的情况,我不明白placement implies 1指的是什么,以及为什么我不能在C中使用{使用此方法{1}}和A 我怎么误解了这条错误信息?

1 个答案:

答案 0 :(得分:0)

这种行为似乎是由于(a) .apply()尝试提供帮助而(b)滥用.apply()输出非标量值的方法。它已在Pandas版本0.21中修复。

我从各种Pandas Github问题页面[123]拼凑了这个解释,其中一些也与{{3}相关联}。它并不是对为什么在实施层面发生这种情况的解释,但它至少在实质上回答了这个问题。
很高兴接受任何相关的更新/编辑。

.apply()试图提供帮助: 如果返回的多维值与输入DataFrame具有相同的形状,apply会将DataFrame推断为输出:

  

TomAugspurger:DataFrame.apply尝试根据结果推断输出。您的输出结果被推断为具有相同列的DataFrame。 this answer

     

jreback:问题是.apply必须试图找出你要返回的内容以及它如何映射到起始数据。 [ref]

滥用.apply()作为输出非标量值的方法:
简而言之,如果你能避免它,请不要这样做。如果必须的话,偶尔也会期待有趣的结果。

  

jreback:请注意,通常不建议返回非标量,并且不能有效支持。 [ref]