【问题标题】:pandas pivot table aggfunc troubleshootingpandas 数据透视表 aggfunc 疑难解答
【发布时间】:2016-09-23 15:41:53
【问题描述】:

这个DataFrame有两列,都是对象类型。

  Dependents Married
0          0      No
1          1     Yes
2          0     Yes
3          0     Yes
4          0      No

我想根据“已婚”汇总“家属”。

table = df.pivot_table(
        values='Dependents',
        index='Married',
        aggfunc = lambda x: x.map({'0':0,'1':1,'2':2,'3':3}).mean())

这行得通,但令人惊讶的是,以下行不通:

table = df.pivot_table(values = 'Dependents', 
        index = 'Married', 
        aggfunc = lambda x: x.map(int).mean())

它将生成一个None

谁能帮忙解释一下?

【问题讨论】:

  • 看起来你在第二组中缺少一组括号。另外,为什么不直接使用 aggfunc=int?
  • 在导入或预处理时,您是否有理由不将整个内容转换为整数? df = pd.read_csv('bleh.csv').assign( Dependents = lambda d: d.Dependents.astype("int")) 或任何类似的方法?
  • @Sohier Dane。我不相信 () 在 lambda 函数周围被遗漏。我试图将一个 pd 系列映射为 str 到 int 然后得到它的平均值。我需要知道已婚与单身的平均受抚养人。
  • @xysmas。是的。转换为 int 会更简单。但是数据不干净,“Dependents”列有“3+”、“3+”和“NaN”等值,在转换之前需要一些预处理。实际上,现在我认为第一种方法看起来很麻烦,但是对于处理除 '1'、'2'、'3' 和 '0' 之外的意外值来说是健壮的。
  • @user2951327 FWIW,我认为如果数据是脏的,那么在枢轴的aggfunc 内清理它是最不直接的方法之一。为什么不先清理它,然后做支点?更容易看到正在发生的事情,并且还允许您执行除旋转之外的其他操作。

标签: python pandas pivot-table


【解决方案1】:

您的问题中提供的两个代码示例都有效。但是,它们并不是实现您想要做的事情的惯用方式——尤其是第一个。

我认为这是获得预期行为的正确方法。

# Test data
df = DataFrame({'Dependents': ['0', '1', '0', '0', '0'],
                'Married': ['No', 'Yes', 'Yes', 'Yes', 'No']})

# Converting object to int
df['Dependents'] = df['Dependents'].astype(int)
# Computing the mean by group
df.groupby('Married').mean()

         Dependents
Married            
No             0.00
Yes            0.33

但是,下面的代码可以工作。

df.pivot_table(values = 'Dependents', index = 'Married', 
               aggfunc = lambda x: x.map(int).mean())

在透视数据之前使用map 转换为int 等效(并且更具可读性)。

df['Dependents'] = df['Dependents'].map(int)
df.pivot_table(values = 'Dependents', index = 'Married')

编辑

如果你有乱七八糟的DataFrame,你可以使用to_numeric,将error参数设置为coerce

如果coerce,则无效解析将设置为NaN

# Test data
df = DataFrame({'Dependents': ['0', '1', '2', '3+', 'NaN'], 
                 'Married': ['No', 'Yes', 'Yes', 'Yes', 'No']})

df['Dependents'] = pd.to_numeric(df['Dependents'], errors='coerce')
print(df)

   Dependents Married
0         0.0      No
1         1.0     Yes
2         2.0     Yes
3         NaN     Yes
4         NaN      No

print(df.groupby('Married').mean())

         Dependents
Married            
No              0.0
Yes             1.5

【讨论】:

  • 是的。我同意它更干净。但我不知道为什么它不起作用。也许还有其他原因。我可以关闭这个问题
  • 太好了,你可以查看答案
  • 您的方法可能不适用于混乱的数据,例如,使用 df = DataFrame({'Dependents': ['0', '1', '2', '3+', 'NaN '], 'Married': ['No', 'Yes', 'Yes', 'Yes', 'No']}),astype(int) 不起作用。 to_numeric 会将 '3+' 转换为 NaN,这可能不是你想要的,`df = df.apply(lambda x: x.map({'0':0,'1':1,'2':2, '3':3, '3+': 3}) 很乱但可以接受。
  • @FrankZhu 感谢您的评论(以及反对票)。请发布您的最佳答案,如果效果良好,我将很乐意投票。
  • 在@Romain上方查看我的答案
【解决方案2】:

我最初的问题是为什么使用 map(int) 的方法 2 不起作用。以上都没有回答我的问题。因此没有最佳答案。

但是,当我回首往事时,我发现现在在 pandas 0.22 中,方法 2 确实有效。我想问题出在熊猫身上。

为了稳健地进行聚合,我的解决方案是

df.pivot_table(
        values='Dependents',
        index='Married',
        aggfunc = lambda x: x.map(lambda x:int(x.strip("+"))).mean())

为了使其更清晰,我想您可以先将“Dependents”列转换为整数,然后进行聚合。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-06-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多