当返回的列表长度与数据框列数相同时,应用 + 列表推导会给出 ValueError
Posted
技术标签:
【中文标题】当返回的列表长度与数据框列数相同时,应用 + 列表推导会给出 ValueError【英文标题】:apply + list comprehension gives ValueError when returned list length is same as number of data frame columns 【发布时间】:2018-05-01 19:55:03 【问题描述】:这个问题来自this comment thread。使用熊猫0.20.3
。
我试图理解为什么 apply()
操作会引发错误:
ValueError: 传递的项目数错误 2,位置暗示 1
Pandas ValueError
的这种特殊风格是 not uncommon,但它通常来自更明显的尝试,即把一堆元素塞进一个为较小容量而设计的数据结构中。这里肯定发生了同样的事情,但我不知道为什么。
给定一个包含整数列 A
和 B
的数据框:
import pandas as pd
df = pd.DataFrame('A': [1,2], 'B': [3,4])
df
A B
0 1 3
1 2 4
我可以构造一个新列C
,它是一列列表。C
中的每个列表都包含来自 A
和 B
的值。C
应如下所示:
C
[1, 3]
[2, 4]
我选择使用apply()
和列表理解来构建C
:
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
指的是什么,以及为什么我不能只使用A
和B
的元素来制作C
中的列表,使用这种方法。
我如何误解了此错误消息?
【问题讨论】:
我无法在0.21
上重现此内容。但我可以告诉你,pandas 特例列表和 numpy 数组与数据框具有相同的宽度。
这也是你可以做df.apply(tuple, 1)
但不能做df.apply(list, 1)
的原因
有趣 - 你能指出我讨论“特殊情况”的任何地方吗?
我认为最相关的链接是:github.com/pandas-dev/pandas/issues/16321
在我尝试之后,df.apply(lambda x: [val for val in x if val != 2], axis=1)
,我感到震惊......
【参考方案1】:
这种行为似乎是由 (a) .apply()
试图提供帮助和 (b) 滥用 .apply()
作为输出手段的混合造成的非标量值。已在 Pandas 版本0.21
中修复。
我从各种 Pandas Github 问题页面 [1、2、3] 拼凑了这个解释,其中一些也链接到 this answer。这并不能真正解释为什么会在实施级别发生这种情况,但它至少实质性地回答了这个问题。 很高兴接受任何相关的更新/编辑。
.apply()
试图提供帮助:
如果返回一个与输入 DataFrame 具有相同形状的多维值,apply
将推断一个 DataFrame 作为输出:
TomAugspurger:DataFrame.apply 尝试根据结果推断输出。您的输出结果被推断为具有相同列的 DataFrame。 [ref]
jreback:问题是 .apply 必须尝试找出您返回的内容以及它如何映射到起始数据。 [ref]
关于滥用 .apply()
作为输出非标量值的一种方式:
简而言之,如果可以避免,请不要这样做。如果必须,期待偶尔有趣的结果。
jreback:请注意,通常不建议返回非标量,也无法有效支持。 [ref]
【讨论】:
以上是关于当返回的列表长度与数据框列数相同时,应用 + 列表推导会给出 ValueError的主要内容,如果未能解决你的问题,请参考以下文章