Pandas Crosstab在同一输出上具有频率,行百分比和col百分比

时间:2016-04-01 19:26:35

标签: python pandas stata

我正在尝试在Stata中复制非常有用的tabulate twoway函数,在同一输出中,您可以看到频率,相应的行百分比和数据中两个分类变量的每种可能组合的相应列百分比

也就是说,结果表中的每个单元格都包含三个与上述数字对应的堆叠值。

Stata中的输出示例:这是单个变量汽车类型的列表,其中,在数据中,我有52个观测值,其中汽车类型为domestic,22个观测值为汽车类型等于foreign

 Domestic   Foreign  Total

 52         22       74 
 70.27      29.73    100.00 
 100.00     100.00   100.00 

在熊猫中可以做到吗?例如:

df = pd.DataFrame({'A' : ['one', 'one', 'two', 'three'] * 6,
                   'B' : ['A', 'B', 'C'] * 8,
                   'C' : ['foo', 'foo', 'foo', 'bar', 'bar', 'bar'] * 4,
                   'D' : np.random.randn(24),
                   'E' : np.random.randn(24)})

会结合的东西

pd.crosstab(df.A,df.B)

pd.crosstab(df.A, df.B).apply(lambda r: r/r.sum(), axis=1)

pd.crosstab(df.A, df.B).apply(lambda r: r/r.sum(), axis=0)

在同一输出上。你怎么看?我正在考虑aggfunc,但在这里我需要获得整个数据帧,而不仅仅是一个系列......

谢谢!

1 个答案:

答案 0 :(得分:1)

考虑使用交叉表的margins将所有三个连接成一个df。下面使用您的示例:

newdf = pd.concat([pd.crosstab(df.A, df.B, margins=True),
                   pd.crosstab(df.A, df.B).apply(lambda r: r/r.sum(), axis=0),                   
                   pd.crosstab(df.A, df.B).apply(lambda r: r/r.sum(), axis=1)])

newdf = newdf.loc[['one','two','three','All']]              # RE-ORDER INDEX VALUES                                 
newdf = newdf[['A', 'B', 'C', 'All']]                       # RE-ORDER COLUMNS 
newdf['All'] = np.where(pd.isnull(newdf['All'])   &         # ROW PERCENTAGES SUM
                        (newdf['A'] + newdf['B'] + newdf['C']==1),
                        1, newdf['All'])
print(newdf)
#              A         B         C   All
# A                                        
# one    4.000000  4.000000  4.000000  12.0
# one    0.500000  0.500000  0.500000   NaN
# one    0.333333  0.333333  0.333333   1.0
# two    2.000000  2.000000  2.000000   6.0
# two    0.250000  0.250000  0.250000   NaN
# two    0.333333  0.333333  0.333333   1.0
# three  2.000000  2.000000  2.000000   6.0
# three  0.250000  0.250000  0.250000   NaN
# three  0.333333  0.333333  0.333333   1.0
# All    8.000000  8.000000  8.000000  24.0