我可以使用交叉表来获取枢轴表以进行求和吗?

时间:2017-03-18 11:34:15

标签: python pandas dataframe pivot-table

我正在使用crosstab对发布商在给定区域内的销售额进行汇总。 原始数据框如下所示:

Publisher   NA_Sales    EU_Sales    JP_Sales
1   Nintendo    29.08   3.58    6.81
2   Nintendo    15.68   12.76   3.79
3   Nintendo    15.61   10.93   3.28
4   Nintendo    11.27   8.89    10.22
5   Nintendo    23.20   2.26    4.22

我现在使用数据透视表进行了操作,我想使用交叉表进行操作。

salespivot1=pd.pivot_table(df, index=df.Publisher,
    aggfunc=np.sum).sort_values('NA_Sales', ascending=False)

创建:

          EU_Sales  JP_Sales    NA_Sales
Publisher           
Nintendo    390.05  454.38  775.61
Electronic Arts 373.91  14.35   599.50
Activision  215.90  6.71    432.59
Sony Computer Entertainment 186.56  74.15   266.17
Ubisoft 161.99  7.52    252.74

但是使用交叉表我无法重新创建这个数据帧,因为无论我做什么,它都会在NA_Sales之上堆叠EU_Sales

salespivot3=pd.crosstab(index=df.Publisher, columns=['NA_Sales', 'EU_Sales'],
    values=df.NA_Sales, aggfunc=sum)

创建:

col_0   NA_Sales
col_1   EU_Sales
Nintendo    775.61
Electronic Arts  599.50
Activision    432.59
Sony Computer Entertainment  266.17
Ubisoft    252.74

如何使用交叉表重新创建数据框以提供与pivot相同的结果?

2 个答案:

答案 0 :(得分:3)

我认为您“误用”pivot_tablecrosstab方法。

Pivot方法假设您将数据集从长格式转换为宽格式。

这是一个小型演示:

来源DF:

In [42]: df
Out[42]:
     A    B      C  D
0  foo  one  small  1
1  foo  one  large  2
2  foo  one  large  2
3  foo  two  small  3
4  foo  two  small  3
5  bar  one  large  4
6  bar  one  small  5
7  bar  two  small  6
8  bar  two  large  7

pivot_table用法:

In [43]: df.pivot_table(values='D', index=['A', 'B'], columns=['C'], aggfunc='sum')
Out[43]:
C        large  small
A   B
bar one    4.0    5.0
    two    7.0    6.0
foo one    4.0    1.0
    two    NaN    6.0

现在使用pd.crosstab()方法的结果相同:

In [44]: pd.crosstab(index=[df.A,df.B], columns=df.C, values=df.D, aggfunc='sum')
Out[44]:
C        large  small
A   B
bar one    4.0    5.0
    two    7.0    6.0
foo one    4.0    1.0
    two    NaN    6.0

对于您的示例数据集,您只需要groupby + sum

In [46]: df
Out[46]:
  Publisher  NA_Sales  EU_Sales  JP_Sales
1  Nintendo     29.08      3.58      6.81
2  Nintendo     15.68     12.76      3.79
3  Nintendo     15.61     10.93      3.28
4  Nintendo     11.27      8.89     10.22
5  Nintendo     23.20      2.26      4.22

In [47]: df.groupby('Publisher', as_index=False).sum()
Out[47]:
  Publisher  NA_Sales  EU_Sales  JP_Sales
0  Nintendo     94.84     38.42     28.32

更新:如果您想要使用crosstab方法生成相同的数据集,可以这样做:

In [63]: x = df.set_index('Publisher').stack().reset_index(name='val')

In [64]: x
Out[64]:
   Publisher   level_1    val
0   Nintendo  NA_Sales  29.08
1   Nintendo  EU_Sales   3.58
2   Nintendo  JP_Sales   6.81
3   Nintendo  NA_Sales  15.68
4   Nintendo  EU_Sales  12.76
5   Nintendo  JP_Sales   3.79
6   Nintendo  NA_Sales  15.61
7   Nintendo  EU_Sales  10.93
8   Nintendo  JP_Sales   3.28
9   Nintendo  NA_Sales  11.27
10  Nintendo  EU_Sales   8.89
11  Nintendo  JP_Sales  10.22
12  Nintendo  NA_Sales  23.20
13  Nintendo  EU_Sales   2.26
14  Nintendo  JP_Sales   4.22

In [65]: pd.crosstab(index=x.Publisher, columns=x.level_1, values=x.val, aggfunc='sum')
Out[65]:
level_1    EU_Sales  JP_Sales  NA_Sales
Publisher
Nintendo      38.42     28.32     94.84

注意:我们首先将原始DF从宽格式转换为长格式,然后使用pd.crosstab

将其转换为宽格式

答案 1 :(得分:3)

您无法直接在当前DF上使用pd.crosstab(),除非您将它们从宽格式转换为长格式,以便生成的标题稍后将作为后续参数传递进入它的函数调用。

这是一个轻微的黑客攻击:

idx = ["Publisher"]
d = pd.melt(df, id_vars=idx)
pd.crosstab(d.Publisher, d.variable, d.value, aggfunc="sum", rownames=idx, colnames=[None])

enter image description here

但老实说,您应该使用专为此目的而设计的groupby / pivot_table方法。