我有样品片段,按预期工作:
进口熊猫作为 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,它是一致的。
问题是为什么它以这种方式工作?
我以前遇到过类似的问题。我认为潜在的问题是当列表中的元素数量与组中的记录数量相匹配时, 它试图解压缩列表,以便列表的每个元素映射到组中的记录。
例如,这将导致列表解包,因为列表的长度与每个组的长度匹配:
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]
我认为这是列表拆包功能的副作用。
我认为这是熊猫的一个错误。你能开一张票吗他们的 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 版本进行测试。
自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]