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

Qua*_*sto 16 python transform pandas pandas-groupby

我有可以按预期工作的示例代码段:

import pandas as pd

df = pd.DataFrame(data={'label': ['a', 'b', 'b', 'c'], 'wave': [1, 2, 3, 4], 'y': [0,0,0,0]})
df['new'] = df.groupby(['label'])[['wave']].transform(tuple)
Run Code Online (Sandbox Code Playgroud)

结果是:

  label  wave  y     new
0     a     1  0    (1,)
1     b     2  0  (2, 3)
2     b     3  0  (2, 3)
3     c     4  0    (4,)
Run Code Online (Sandbox Code Playgroud)

如果不是,tuple我给出set, frozenset, dict,它会以类似的方式工作,但是如果给出,list我将得到完全出乎意料的结果:

df['new'] = df.groupby(['label'])[['wave']].transform(list)

  label  wave  y  new
0     a     1  0    1
1     b     2  0    2
2     b     3  0    3
3     c     4  0    4
Run Code Online (Sandbox Code Playgroud)

有一种变通方法以获得预期的结果:

df['new'] = df.groupby(['label'])[['wave']].transform(tuple)['wave'].apply(list)

  label  wave  y     new
0     a     1  0     [1]
1     b     2  0  [2, 3]
2     b     3  0  [2, 3]
3     c     4  0     [4]
Run Code Online (Sandbox Code Playgroud)

我考虑过可变性/不变性(列表/元组),但是对于集合/冻结集,它是一致的。

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

All*_*len 6

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

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

df.groupby(['label'])[['wave']].transform(lambda x: list(x))
    wave
0   1
1   2
2   3
3   4
Run Code Online (Sandbox Code Playgroud)

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

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

    wave
0   [1, 0]
1   [2, 3, 0]
2   [2, 3, 0]
3   [4, 0]
Run Code Online (Sandbox Code Playgroud)

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

  • 我创建了一个问题https://github.com/pandas-dev/pandas/issues/28246 (2认同)
  • @Shinjo与大熊猫相关,type(df [['wave']])是DataFrame,type(df ['wave'])是Series。 (2认同)

jot*_*tbe 3

我认为这是熊猫的一个错误。您可以在他们的 github页面上开票吗?

起初我想,这可能是,因为list只是没有正确处理作为 的参数.transform,但如果我这样做:

def create_list(obj):
    print(type(obj))
    return obj.to_list()

df.groupby(['label'])[['wave']].transform(create_list)
Run Code Online (Sandbox Code Playgroud)

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

df.groupby(['label'])['wave'].agg(list)
Out[179]: 
label
a       [1]
b    [2, 3]
c       [4]
Name: wave, dtype: object
Run Code Online (Sandbox Code Playgroud)

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

顺便提一句。我还发现不同的行为很可疑,如果您将元组应用于分组系列和分组数据框,就会出现这种情况。例如,如果transform应用于一系列而不是 DataFrame,则结果也不是包含列表的系列,而是包含以下内容的系列ints(请记住,[['wave']]它创建的单列数据帧transform(tuple)确实返回了元组):

df.groupby(['label'])['wave'].transform(tuple)
Out[177]: 
0    1
1    2
2    3
3    4
Name: wave, dtype: int64
Run Code Online (Sandbox Code Playgroud)

如果我再次这样做,agg而不是transform它对两者都有效['wave']并且[['wave']]

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