【问题标题】:Pandas nested groupby gives unexpected results熊猫嵌套 groupby 给出了意想不到的结果
【发布时间】:2019-07-30 22:59:12
【问题描述】:

我正在解决一个问题,我在 pandas DataFrame 上使用嵌套的 groupby.apply。在第一次应用期间,我添加了一个用于第二个内部 groupby.apply 的列。综合结果在我看来是错误的。谁能向我解释为什么会发生以下现象以及如何可靠地解决它?

这是一个最小的例子:

import numpy as np
import pandas as pd

T = np.array( [
        [1,1,1],
        [1,1,1],
        [1,2,2],
        [1,2,2],
        [2,1,3],
        [2,1,3],
        [2,2,4],
        [2,2,4],
])

df = pd.DataFrame(T, columns= ['a','b','c' ])

print(df)


def foo2(x):
    return x

def foo(x):

    print("*" * 80 )

    # Add column d and groupby/apply on column 'd'
    x['d'] = [1, 1, 2, 2]
    x = x.groupby('d').apply(foo2)

    print(x)

    print("*" * 80)
    return x


# Apply first groupby/apply on column 'a'
df = df.groupby('a').apply( foo)

print("*"*80)
print("*"*80)

print(df)

当我在我的 Windows 笔记本电脑上运行上述代码时,我得到了预期的结果

     a  b  c  d
a              
1 0  1  1  1  1
  1  1  1  1  1
  2  1  2  2  2
  3  1  2  2  2
2 4  2  1  3  1
  5  2  1  3  1
  6  2  2  4  2
  7  2  2  4  2

在 Mac 上运行相同的代码

     a  b  c  d
a              
1 0  1  1  1  1
  1  1  1  1  1
  2  1  2  2  2
  3  1  2  2  2
2 4  1  1  3  1
  5  1  1  3  1
  6  1  2  4  2
  7  1  2  4  2

这里的问题是,在“a”列中,最后 4 个条目是 1,而在 Windows 机器上它们应该是 2。

编辑:

两者的 Pandas 版本:0.24.2

Windows 上的 Python 版本:3.7.3

Mac 上的 Python 版本:3.7.4

【问题讨论】:

  • 请同时发布pandas版本和python版本
  • 谢谢,我做了修改。

标签: python pandas pandas-groupby


【解决方案1】:

[Mac、Python:3.6.8]

我的想法是嵌套DataFrame.applys 的预期行为会有点令人费解,无法调试。我的建议是通过模仿你想要从apply 实现的目标来切入正题(即先映射然后减少):

  1. Map:使用python原生的map方法,后跟
  2. 减少:使用pandas.concat 合并结果
import numpy as np
import pandas as pd

def my_apply(df, f):
    return pd.concat(map(f, df))

def foo(x):
    group, grouped = x
    grouped['d'] = [1, 1, 2, 2]
    return grouped.groupby('d').apply(lambda x: x)

T = np.array([[1,1,1]]*2 + [[1,2,2]]*2 +
             [[2,1,3]]*2 + [[2,2,4]]*2)           
df = pd.DataFrame(T, columns= ['a','b','c' ])
df = my_apply(df.groupby('a'), foo)
print(df)

结果:

   a  b  c  d
0  1  1  1  1
1  1  1  1  1
2  1  2  2  2
3  1  2  2  2
4  2  1  3  1
5  2  1  3  1
6  2  2  4  2
7  2  2  4  2

注意事项:

  1. 我没有尝试解决导致 Mac/Windows 之间的这种性能差异的实现/架构差异]
  2. 我已经缩小了您的示例,将 foo2 替换为 lambda,随时换回。
  3. 以上代码将抛出以下警告A value is trying to be set on a copy of a slice from a DataFrame [...]。这是因为我们故意设置了一个副本的值。这是预期的行为,而不是错误。不幸的是,pandas 将此操作解释为错误,因为通常情况下可能是这样。

【讨论】:

  • 嘿,谢谢,代码抛出以下警告。也许这与熊猫失败的原因有关:SettingWithCopyWarning: A value is trying to be set on a copy of a slice from a DataFrame。尝试改用 .loc[row_indexer,col_indexer] = value 查看文档中的注意事项:pandas.pydata.org/pandas-docs/stable/… grouped['d'] = [1, 1, 2, 2]。
  • 我添加了关于(预期)警告的注释。您可以禁用它,但“真正”的解决方法是使用grouped.copy() 复制grouped 对象,但对于性能不会很高的大型数据帧,所以我认为最好制作处理警告。我非常怀疑这与问题中的问题有关。我最好的猜测是,组索引在 Mac 版 pandas 中的某个地方被吸收了。实际上,apply 和 group by 方法可能并不打算以这种方式进行操作。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-07-21
  • 1970-01-01
  • 1970-01-01
  • 2019-05-19
  • 2017-01-05
  • 2021-10-14
  • 1970-01-01
相关资源
最近更新 更多