40_Pandas中crosstab进行交叉制表(计算每个类别的出现次数和频率)
可以使用pandas.crosstab()函数完成交叉表分析。 可以为每个类别的分类数据(分类数据,定性数据)计算样本数(出现次数/频率)。
如果要计算每个类别的平均值而不是出现次数,请使用数据透视表pandas.pivot_table()。
这里,
- pandas.crosstab()函数的基本用法
- 计算每个类别的小计/总计:参数margins
- 标准化整个/行/列:参数normalize
将予以描述。 将以泰坦尼克号的生存信息数据为例。
import pandas as pd
df = pd.read_csv('./data/40/train.csv', index_col=0).drop(['Name', 'Ticket', 'SibSp', 'Parch'], axis=1)
print(df.head())
# Survived Pclass Sex Age Fare Cabin Embarked
# PassengerId
# 1 0 3 male 22.0 7.2500 NaN S
# 2 1 1 female 38.0 71.2833 C85 C
# 3 1 3 female 26.0 7.9250 NaN S
# 4 1 1 female 35.0 53.1000 C123 S
# 5 0 3 male 35.0 8.0500 NaN S
pandas.crosstab()函数的基本用法
在第一个参数索引中指定pandas.DataFrame列(= pandas.Series)作为结果行标题,在第二个参数列中指定pandas.DataFrame列(= pandas.Series)作为结果列标题。
注意,与pandas.pivot_table()不同,它不是由pandas.DataFrame对象及其列名指定的。
print(pd.crosstab(df['Sex'], df['Pclass']))
# Pclass 1 2 3
# Sex
# female 94 76 144
# male 122 108 347
pandas.crosstab()函数返回pandas.DataFrame。
print(type(pd.crosstab(df['Sex'], df['Pclass'])))
# <class 'pandas.core.frame.DataFrame'>
还可以在参数索引和列中指定pandas.Series的列表。结果以多索引(分层索引)pandas.DataFrame的形式返回。
print(pd.crosstab([df['Sex'], df['Survived']], [df['Pclass'], df['Embarked']]))
# Pclass 1 2 3
# Embarked C Q S C Q S C Q S
# Sex Survived
# female 0 1 0 2 0 0 6 8 9 55
# 1 42 1 46 7 2 61 15 24 33
# male 0 25 1 51 8 1 82 33 36 231
# 1 17 0 28 2 0 15 10 3 34
请参阅以下文章,了解如何选择多索引pandas.DataFrame的行和列。
计算每个类别的小计/总计:参数margins
如果参数margin为True,则可以计算每个类别的小计和总计。
print(pd.crosstab([df['Sex'], df['Survived']], [df['Pclass'], df['Embarked']],
margins=True))
# Pclass 1 2 3 All
# Embarked C Q S C Q S C Q S
# Sex Survived
# female 0 1 0 2 0 0 6 8 9 55 81
# 1 42 1 46 7 2 61 15 24 33 231
# male 0 25 1 51 8 1 82 33 36 231 468
# 1 17 0 28 2 0 15 10 3 34 109
# All 85 2 127 17 3 164 66 72 353 889
可以通过参数margins_name指定小计/总行标签/列标签。默认为“all”。
print(pd.crosstab([df['Sex'], df['Survived']], [df['Pclass'], df['Embarked']],
margins=True, margins_name='Total'))
# Pclass 1 2 3 Total
# Embarked C Q S C Q S C Q S
# Sex Survived
# female 0 1 0 2 0 0 6 8 9 55 81
# 1 42 1 46 7 2 61 15 24 33 231
# male 0 25 1 51 8 1 82 33 36 231 468
# 1 17 0 28 2 0 15 10 3 34 109
# Total 85 2 127 17 3 164 66 72 353 889
标准化整个/行/列:参数normalize
指定参数normalize时,可以对整个,行和列的结果进行1归一化(归一化)。 如果normalize = True或normalize =‘all’,则将其标准化以使总数为1。
print(pd.crosstab(df['Sex'], df['Pclass'], margins=True, normalize=True))
# Pclass 1 2 3 All
# Sex
# female 0.105499 0.085297 0.161616 0.352413
# male 0.136925 0.121212 0.389450 0.647587
# All 0.242424 0.206510 0.551066 1.000000
如果normalize =‘index’,则将其标准化,以使每行的总数为1。
print(pd.crosstab(df['Sex'], df['Pclass'], margins=True, normalize='index'))
# Pclass 1 2 3
# Sex
# female 0.299363 0.242038 0.458599
# male 0.211438 0.187175 0.601386
# All 0.242424 0.206510 0.551066
如果normalize =‘columns’,则将其标准化,以使每列的总数为1。
print(pd.crosstab(df['Sex'], df['Pclass'], margins=True, normalize='columns'))
# Pclass 1 2 3 All
# Sex
# female 0.435185 0.413043 0.293279 0.352413
# male 0.564815 0.586957 0.706721 0.647587
请注意,如果在列表中为参数margins = True和参数索引和列指定了多列,则如果在指定方向上对多索引进行标准化,则会发生错误。
# print(pd.crosstab(df['Sex'], [df['Pclass'], df['Embarked']],
# margins=True, normalize=True))
# TypeError: Expected tuple, got str
print(pd.crosstab(df['Sex'], [df['Pclass'], df['Embarked']],
margins=True, normalize='index'))
# Pclass 1 2 \
# Embarked C Q S C Q S
# Sex
# female 0.137821 0.003205 0.153846 0.022436 0.006410 0.214744
# male 0.072790 0.001733 0.136915 0.017331 0.001733 0.168111
# All 0.095613 0.002250 0.142857 0.019123 0.003375 0.184477
# Pclass 3
# Embarked C Q S
# Sex
# female 0.073718 0.105769 0.282051
# male 0.074523 0.067591 0.459272
# All 0.074241 0.080990 0.397075
# print(pd.crosstab(df['Sex'], [df['Pclass'], df['Embarked']],
# margins=True, normalize='columns'))
# ValueError: Length of new names must be 1, got 2
如果margins = False(默认值),则没有问题。
print(pd.crosstab(df['Sex'], [df['Pclass'], df['Embarked']], normalize=True))
# Pclass 1 2 \
# Embarked C Q S C Q S
# Sex
# female 0.048369 0.001125 0.053993 0.007874 0.002250 0.075366
# male 0.047244 0.001125 0.088864 0.011249 0.001125 0.109111
# Pclass 3
# Embarked C Q S
# Sex
# female 0.025872 0.03712 0.098988
# male 0.048369 0.04387 0.298088
print(pd.crosstab(df['Sex'], [df['Pclass'], df['Embarked']], normalize='index'))
# Pclass 1 2 \
# Embarked C Q S C Q S
# Sex
# female 0.137821 0.003205 0.153846 0.022436 0.006410 0.214744
# male 0.072790 0.001733 0.136915 0.017331 0.001733 0.168111
# Pclass 3
# Embarked C Q S
# Sex
# female 0.073718 0.105769 0.282051
# male 0.074523 0.067591 0.459272
print(pd.crosstab(df['Sex'], [df['Pclass'], df['Embarked']], normalize='columns'))
# Pclass 1 2 3 \
# Embarked C Q S C Q S C
# Sex
# female 0.505882 0.5 0.377953 0.411765 0.666667 0.408537 0.348485
# male 0.494118 0.5 0.622047 0.588235 0.333333 0.591463 0.651515
# Pclass
# Embarked Q S
# Sex
# female 0.458333 0.249292
# male 0.541667 0.750708