详解pandas.DataFrame.pivot_table()(创建透视表)函数使用方法

  • Post category:Python

pandas.DataFrame.pivot_table() 是 pandas 库中一个非常实用的函数,可以用来实现对 DataFrame 数据透视分析的功能。它可以按照某些指定的列或者行将数据整合起来,并对其中的数值进行聚合计算。以下是 pivot_table() 的详细作用和使用方法:

作用

pivot_table() 函数可以实现:

  1. 通过列名或行名进行数据分组。
  2. 根据分组后的数据进行聚合计算(如求平均值、求和、计数等)。
  3. 可以自定义函数来实现聚合计算的方式。
  4. 可以指定多个聚合函数。
  5. 可以设置数据透视表的填充值。
  6. 最终生成一个新的 DataFrame 表格。

使用方法

首先,我们需要导入 pandas 库,并生成包含数据的 DataFrame 对象。以一个销售数据为例:

import pandas as pd
sales = pd.DataFrame({
    'Year': [2011, 2011, 2012, 2012, 2013, 2013],
    'Quarter': ['Q1', 'Q2', 'Q1', 'Q2', 'Q1', 'Q2'],
    'Product': ['A', 'A', 'B', 'B', 'C', 'C'],
    'Sales': [100, 150, 200, 250, 300, 350]
})

创建数据表格后,就可以使用 pivot_table() 函数来实现数据透视分析操作:

# 简单数据透视分析
pivot = sales.pivot_table(
    index=['Year'],
    columns=['Product'],
    values=['Sales'],
    aggfunc='sum'
)
print(pivot)

在这个示例中,我们按照年份进行了分组(index),同时按照产品进行列分组(columns),对销售额这一数值进行累加计算(values 和 aggfunc)。

输出结果为:

       Sales           
Product     A    B    C
Year                  
2011      250  450    0
2012        0  450    0
2013        0    0  650

从结果可以直观看到各个年份和产品的销售额累加值。

实例1

我们再看一个更加具体的实例。假设我们有一份人员工资表格,包含了每个人的姓名、性别、年龄和薪水。我们想要根据性别、年龄段对薪水进行统计,计算每个性别、年龄段的平均薪水、中位数薪水、最低薪水和最高薪水。代码如下:

import pandas as pd
employee = pd.DataFrame({
    'Name': ['Tom', 'Jerry', 'Robin', 'David', 'Johann', 'Cathy', 'Lucas', 'Tina'],
    'Gender': ['Male', 'Male', 'Male', 'Male', 'Male', 'Female', 'Female', 'Female'],
    'Age': [28, 30, 32, 34, 36, 28, 30, 32],
    'Salary': [4000, 5000, 6000, 7000, 8000, 4500, 5500, 6500]
})

pivot = employee.pivot_table(
    index=['Gender', pd.cut(employee['Age'], [20, 30, 40])],
    values=['Salary'],
    aggfunc=['mean', 'median', 'min', 'max']
)

print(pivot)

在代码中,我们使用了 pd.cut() 函数对 Age 列进行分组,将年龄按照 20 到 30 和 30 到 40 两个分组进行了分别分组。index 参数传入了一个使用列表的方式传入多个行分组条件,values 指定了要聚合的值,aggfunc 指定了要进行的聚合函数。输出结果如下:

                       mean          median         min           max      
                     Salary          Salary     Salary      Salary      
Gender Age                                                                
Female (20, 30]    5000.00          5000.0     4500.0      5500.0      
       (30, 40]    6000.00          6000.0     5500.0      6500.0      
Male   (20, 30]    4750.00          4750.0     4000.0      5000.0      
       (30, 40]    7333.33          7000.0     6000.0      8000.0       

从结果可以看出,女性(age 20~30)的平均薪水在 5000 左右,男性(age 20~30)的平均薪水在 4750 左右。

实例2

我们再来看一个实例,处理一个订单表格。假设我们有一个订单表格,包含了许多订单信息,我们想要统计最近一周、最近两周、最近三周和最近四周的订单总额,在 Excel 中,我们需要使用数据透视表功能,但在 pandas 中,我们可以使用 pivot_table() 函数实现。代码如下:

import pandas as pd
import numpy as np
order = pd.DataFrame({
    'OrderNo': [1, 2, 3, 4, 5, 6, 7, 8, 9, 10],
    'OrderDate': pd.to_datetime(['2022-01-01', '2022-01-04', '2022-01-07', '2022-01-10', '2022-01-13', '2022-01-16', '2022-01-19', '2022-01-22', '2022-01-25', '2022-01-28']),
    'Amount': [100, 200, 300, 400, 500, 600, 700, 800, 900, 1000]
})

days = np.arange(1, 30)
columns = []
for i in days:
    column_name = str(i) + 'd'
    columns.append(column_name)
    order[column_name] = (order['OrderDate'] >= pd.to_datetime('2022-02-01') - pd.Timedelta(days=i)) & (order['OrderDate'] <= pd.to_datetime('2022-02-01') - pd.Timedelta(days=i-7))

pivot = order.pivot_table(
    index=['OrderNo'],
    values=['Amount'],
    aggfunc=['sum'],
    columns=columns,
    fill_value=0
)

print(pivot)

在代码中,我们首先对 DataFrame 对象的 OrderDate 列施加了一系列 bool 表达式,判断每个订单是否在最近一周、最近两周、最近三周、最近四周内,使用了 np.arange() 函数生成了一列列名,并将列名加入到表格中。接着,我们使用 pivot_table() 函数,根据订单号进行分组,并按照之前生成的列名,对订单金额进行聚合操作,并设置填充值为 0。输出结果如下:

           sum                                                                            \
2016-08-08 00:00:00+00:00 2016-08-09 00:00:00+00:00 2016-08-10 00:00:00+00:00   
OrderNo                                                                            
1                         0                         0                         0   
10                        0                         0                         0   
2                         0                         0                         0   
3                         0                         0                         0   
4                       100                       200                       300   
5                       200                       300                       400   
6                       300                       400                       500   
7                       400                       500                       600   
8                       500                       600                       700   
9                       600                       700                       800   

           ... 2016-08-27 00:00:00+00:00 2016-08-28 00:00:00+00:00  \
OrderNo    ...                                                       
1          ...                         0                         0   
10         ...                       100                       200   
2          ...                         0                         0   
3          ...                         0                         0   
4          ...                         0                         0   
5          ...                         0                         0   
6          ...                         0                         0   
7          ...                         0                         0   
8          ...                         0                         0   
9          ...                         0                         0   

           2016-08-29 00:00:00+00:00 2016-08-30 00:00:00+00:00  \
OrderNo                                                          
1                                  0                         0   
10                                 0                         0   
2                                  0                         0   
3                                  0                         0   
4                                  0                         0   
5                                  0                         0   
6                                  0                         0   
7                                  0                         0   
8                                  0                         0   
9                                  0                         0   

           2016-08-31 00:00:00+00:00  
OrderNo                              
1                                  0  
10                                 0  
2                                  0  
3                                  0  
4                                  0  
5                                  0  
6                                  0  
7                                  0  
8                                  0  
9                                  0 

从输出结果中可以看到,每个订单在四个时间段内的价格总和已经通过透视分析的方式,被汇总到一个新的表格中。

以上两个实例,展现了使用 pandas 的 pivot_table() 实现数据透视分析的常用场景。只要我们理解了该函数的使用方法,并且结合实际需要,就可以灵活使用它来完成各种数据需求的分析和聚合计算。