熊猫转换列表的不一致行为

共3个回答, 标签: python pandas transform pandas-groupby

我有样品片段,按预期工作:

进口熊猫作为 pd

Df = pd。 dataFrame (数据 = {'label': ['a','b','b','c'],'wave': [1,2,3,4],'y': [0,0,0,0]})
Df ['new'] = df.groupby (['label']) [['wave']]。变换 (元组)

结果是:

标签波 y 新
0 一 1 一 0 (1,)
1 b 2 0 (2,3)
2 b 3 0 (2,3)
3 c 4 0 (4,)

它适用于 analagously,如果不是tuple in transform I give set, frozenset, dict, but if I give list我得到了完全意想不到的结果:

Df ['new'] = df.groupby (['label']) [['wave']]。变换 (列表)

标签波 y 新
0 一 1
1 b 2 0 2
2 b 3 0 3
3 c 4 0 0 4

有一个解决方法来获得预期的结果:

Df ['new'] = df.groupby (['label']) [['wave']。变换 (元组) ['wave']。应用 (列表)

标签波 y 新
0 一 1 一 0 [1]
1 b 2 0 [2,3]
2 b 3 0 [2,3]
3 c 4 0 [4]

我想到了可变性/不变性 (列表/元组),但是对于 set/frozenset,它是一致的。

问题是为什么它以这种方式工作?

第1个答案

我以前遇到过类似的问题。我认为潜在的问题是当列表中的元素数量与组中的记录数量相匹配时, 它试图解压缩列表,以便列表的每个元素映射到组中的记录。

例如,这将导致列表解包,因为列表的长度与每个组的长度匹配:

Df.groupby (['label']) [['wave']].transform (lambda x: list (x))
波浪
0 1
1 2
2 3
3 4

但是,如果列表的长度与每个组不同,您将获得所需的行为:

Df.groupby (['label']) [['wave']].transform (lambda x: list (x) [0])

波浪
0 [1,0]
1 【 2,3,0 】
2 【 2,3,0 】
3 [4,0]

我认为这是列表拆包功能的副作用。

第2个答案

我认为这是熊猫的一个错误。你能开一张票吗他们的 github请页?

起初我想,可能是,因为list is just not handeled correctly as argument to .transform,但如果我这样做:

Def create_list (obj):
打印 (类型 (obj))
返回 obj.to_list ()

Df.groupby (['label']) [['wave'].transform (create_list)

我得到了同样意想不到的结果。然而,如果agg方法使用,它直接工作:

Df.groupby (['label']) ['wave'].agg (列表)
Out [179]:
标签
A [1]
B [2,3]
C [4]
名称: wave,dtype: 对象

我无法想象这是有意的行为。

顺便说一句。我还发现不同的行为可疑,如果你将元组应用于分组系列和分组数据帧,就会出现这种情况。例如,如果transform is applied to a series instead of a DataFrame, the result also is not a series containing lists, but a series containing ints (remember for [['wave']] which creates a one-columed dataframe transform(tuple)确实返回元组):

Df.groupby (['label']) ['wave'].transform (元组)
Out [177]:
0 1
1 2
2 3
3 4
名称: wave,dtype: int64

如果我再这样做agg instead of transform it works for both ['wave'] and [['wave']]

我在 ubuntu X86_64 系统上使用 0.25.0 版本进行测试。

第3个答案

DataFrames主要用于处理 2D 数据,包括数组而不是标量值可能会偶然发现这样的警告。

pd.DataFrame.trasnform is originally implemented on top of .agg:

# Pandas/core/generic.py
@ Appender (_ shared_docs [“transform”] % dict (轴 = “”,* * _ shared_doc_kwargs))
Def transform (self,func,* args,* * kwargs):
结果 = self.agg (func,* args,* * kwargs)
如果 is_scalar (结果) 或 len (结果)!= len (自我):
引发 ValueError (“转换不能产生” “聚合结果”)

返回结果

然而,transform总是返回一个必须与 self 长度相同的数据帧,self 本质上是输入。

当你做一个.agg function on the DataFrame,它工作正常:

Df.groupby (“标签”) [“波”].agg (列表)
标签
A [1]
B [2,3]
C [4]
名称: wave,dtype: 对象

问题被引入时transform tries to return a Series长度相同。

在转变的过程中groupby element which is a slice from self然后再次连接,列表被解压缩到与 @ Allen 提到的索引长度相同的长度。

然而,当他们不对齐时,就不要打开包装:

Df.groupby (['标签']) [['波']]。变换 (λ x: 列表 (x) + [1])
波浪
0 [1,1]
1 【 2,3,1 】
2 【 2,3,1 】
3 [4,1]

解决此问题的方法可能是避免transform:

Df = pd。 dataFrame (数据 = {'label': ['a','b','b','c'],'wave': [1,2,3,4],'y': [0,0,0,0]})
Df = df.merge (df.groupby ('label') ['wave'].agg (list).rename ('new'),on = 'label')
Df
标签波 y 新
0 一 1 一 0 [1]
1 b 2 0 [2,3]
2 b 3 0 [2,3]
3 c 4 0 [4]

相关问题

通过随机抽样其他列数据创建新列 如何使用熊猫获得包括每一个组合的计数 如何有效地展开矩阵的值与小块? 如何破坏 Python 对象并释放内存 将具有特殊格式的文本文档转换为熊猫数据框架 用两本字典绘制一只熊猫专栏图 熊猫转换列表的不一致行为 根据给定条件过滤数据框并添加新列 动态列名的 Pandas 聚合 如果我使用 pandas 为同一项目同时具有 True 和 False 行,则获取 True 行。