python 利用panda 实现列联表(交叉表)

  • Post category:Python

下面是详细讲解“python利用panda实现列联表(交叉表)”的完整攻略。

什么是列联表/交叉表?

列联表/交叉表是一种可以统计两个或多个变量的频次分布情况的数据表格。其可以帮助我们了解两个或多个变量之间的关系,是数据分析和数据探索中常用的统计分析工具。

使用pandas实现列联表/交叉表

在Python中,我们可以使用pandas库来实现列联表/交叉表。pandas库是一个用于数据分析的开源Python库,提供了许多数据处理和数据分析的工具。下面是使用pandas库实现列联表/交叉表的步骤:

1. 导入pandas库

首先,我们需要导入pandas库。可以使用以下代码:

import pandas as pd

2. 创建数据集

接下来,我们需要创建一个数据集。这里,我们以学生是否喜欢打篮球和是否喜欢唱歌作为两个变量,创建一个包含10个学生的数据集。可以使用以下代码:

data = {'basketball': [1, 1, 1, 0, 1, 0, 0, 1, 0, 0],
        'singing': [1, 1, 0, 1, 0, 1, 0, 0, 1, 0]}

df = pd.DataFrame(data)

这里,data是一个字典,它包含两个键值对,分别是basketball和singing。每个键值对中的值是一个列表,表示学生的回答情况。我们将这个字典转换为一个DataFrame对象,即可创建一个数据集。

3. 计算交叉表

接下来,我们需要计算交叉表。可以使用以下代码:

pd.crosstab(df['basketball'], df['singing'])

这里,我们使用crosstab函数计算交叉表。函数的两个参数分别为需要计算交叉表的两个变量。当我们想要统计多个变量时,可以将这些变量作为参数传递给crosstab函数。

运行上面的代码,即可得到一个2×2的交叉表,表示学生们喜欢打篮球和唱歌的频次分布情况:

singing      0  1
basketball      
0           3  2
1           1  4

这个交叉表表示,有3个学生既不喜欢打篮球也不喜欢唱歌,1个学生喜欢打篮球但不喜欢唱歌,2个学生喜欢唱歌但不喜欢打篮球,4个学生既喜欢打篮球也喜欢唱歌。

4. 添加行/列的总计

若我们想在交叉表中添加行/列的总计,可以使用以下代码:

pd.crosstab(df['basketball'], df['singing'], margins=True)

运行上面的代码,即可得到以下的交叉表:

singing      0  1  All
basketball            
0           3  2    5
1           1  4    5
All         4  6   10

这个交叉表中,我们新增了行和列的总计,分别在行/列的最后一行和最后一列。

5. 添加行/列的比例

若我们想在交叉表中添加行/列的比例,可以使用以下代码:

pd.crosstab(df['basketball'], df['singing'], normalize='index')

这里,我们使用了normalize参数,并将其设置为’index’。这意味着我们需要将每一行的值转换为其所在行的比例。我们也可以将normalize参数设置为’columns’,表示将每一列的值转换为其所在列的比例。

运行上面的代码,即可得到以下的交叉表:

singing           0    1
basketball             
0           0.6000 0.4000
1           0.2000 0.8000

这个交叉表中,我们新增了每行的比例,表示喜欢或不喜欢打篮球的学生中,有多少比例同时喜欢或不喜欢唱歌。

示例说明

以下是两个示例说明:

示例1:

假设我们有一批数据,包含三个变量:性别、是否有小孩、是否购买房产。我们想要了解这三个变量之间的关系,可以使用列联表/交叉表。

首先,我们创建一个包含100个样本的数据集,其中性别、是否有小孩、是否购买房产分别表示为gender、have_child和buy_house。可以使用以下代码:

import pandas as pd
import numpy as np

data = {'gender': np.random.choice(['male', 'female'], size=100),
        'have_child': np.random.choice(['yes', 'no'], size=100),
        'buy_house': np.random.choice(['yes', 'no'], size=100)}

df = pd.DataFrame(data)

接下来,我们可以使用crosstab函数计算交叉表。可以使用以下代码:

pd.crosstab(df['gender'], [df['have_child'], df['buy_house']], margins=True)

这里,我们统计了性别、是否有小孩、是否购买房产之间的频次分布情况,并添加了行和列的总计。运行上面的代码,即可得到一个类似下面这样的交叉表:

have_child  no        yes      All
buy_house   no   yes  no   yes     
gender                             
female      8     7   13   11    39
male       12    13   11   15    51
All        20    20   24   26   100

这个交叉表中,我们可以看出有多少女性和男性购买房产或不购买房产,在购买房产的人群中,又有多少人有小孩或没有小孩等等。

示例2:

假设我们有一批数据,包含两个变量:小时数、学生成绩。我们想要了解学生每周花费的小时数和成绩之间的关系,可以使用列联表/交叉表。

首先,我们创建一个包含10个样本的数据集,其中小时数表示为hours,学生成绩表示为grades。可以使用以下代码:

import pandas as pd
import numpy as np

data = {'hours': [5, 7, 6, 8, 4, 5, 6, 7, 9, 8],
        'grades': [70, 80, 75, 85, 65, 70, 80, 90, 92, 88]}

df = pd.DataFrame(data)

接下来,我们可以使用cut函数将小时数划分为若干个区间,并统计每个区间内的学生成绩分布情况。可以使用以下代码:

pd.crosstab(pd.cut(df['hours'], bins=3), columns=pd.cut(df['grades'], bins=[0, 60, 70, 80, 90, 100]), normalize='index')

这里,我们使用了pd.cut函数将hours列划分为三个区间,并使用了bins参数。我们还使用了columns参数,将成绩划分为五个区间。normalize参数表示我们需要计算每行的比例。

运行上面的代码,即可得到以下的交叉表:

grades       (0, 60] (60, 70] (70, 80] (80, 90] (90, 100]
hours                                                     
(3.998, 5.333]   0.00     0.33     0.33     0.33       0.00
(5.333, 6.667]   0.00     0.33     0.33     0.33       0.00
(6.667, 8.0]     0.00     0.00     0.20     0.30       0.50

这个交叉表中,我们可以看出成绩和学习时长的分布情况,从而了解学生们的学业表现。