> 技术文档 > 【Python】数据处理工具:Pandas详细指南_pandas python

【Python】数据处理工具:Pandas详细指南_pandas python


文章目录

  • 一、前言
    • 1.1 什么是Pandas?
    • 1.2 安装Pandas
  • 二、Pandas 数据相关
    • 2.1 Pandas核心数据结构
      • 1. Series
      • 2. DataFrame
    • 2.2 数据读取与写入
    • 2.3 数据探索与清洗
      • 查看数据
      • 处理缺失值
      • 数据筛选
    • 2.4 数据操作
      • 1. 排序:
      • 2. 分组
        • df.groupby
        • 代码示例
      • 3. 合并数据
        • pd.concat
        • 使用示例:按行合并 DataFrame
        • pd.merge
        • 使用示例:SQL风格的合并
      • 4. 应用函数
        • series.apply
        • 使用示例:将 `Age` 列的值乘以 2
        • df.apply
        • 使用示例:按行计算 `Age` 和 `Weight` 的乘积
    • 2.5 时间序列处理
    • 2.6 数据可视化
    • 2.7 性能优化技巧
  • 三、代码示例
    • 示例1:销售数据分析
    • 示例2:客户细分

一、前言

1.1 什么是Pandas?

Pandas 是Python中最流行的数据处理和分析库之一,它提供了高效、灵活且易于使用的数据结构,使得数据清洗、分析和处理变得简单直观。Pandas的名字来源于\"Panel Data\"(面板数据)和\"Python Data Analysis\"(Python数据分析)的组合。

Pandas最初由Wes McKinney于2008年开发,现已成为数据科学领域的标准工具之一,广泛应用于金融、统计、社会科学和许多工程领域。

下面是Pandas的使用与相关接口进行介绍,很多接口的参数较多与复杂,这里只对部分进行解释,感兴趣的话可以去看官方文档:

pandas documentation


1.2 安装Pandas

在开始使用Pandas之前,需要先安装它。直接通过pip安装即可:

pip install pandas# 如果使用Anaconda发行版conda install pandas

二、Pandas 数据相关

2.1 Pandas核心数据结构

Pandas有两个主要的数据结构:SeriesDataFrame

1. Series

Series是一维的标签化数组,可以保存任何数据类型(整数、字符串、浮点数、Python对象等)。

import pandas as pd# 创建一个Seriess = pd.Series([1, 3, 5, 7, 9])print(s)

输出结果:

0 11 32 53 74 9dtype: int64

2. DataFrame

DataFrame是一个二维的标签化数据结构,可以看作是由多个Series组成的字典。

# 创建一个DataFramedata = { \'Name\': [\'Alice\', \'Bob\', \'Charlie\', \'David\'], \'Age\': [25, 30, 35, 40], \'City\': [\'New York\', \'Paris\', \'London\', \'Tokyo\']}df = pd.DataFrame(data)print(df)

输出结果:

 Name Age City0 Alice 25 New York1 Bob 30 Paris2 Charlie 35 London3 David 40 Tokyo

2.2 数据读取与写入

Pandas支持多种数据格式的读写操作:

# 读取CSV文件df = pd.read_csv(\'data.csv\')# 读取Excel文件df = pd.read_excel(\'data.xlsx\')# 读取JSON文件df = pd.read_json(\'data.json\')# 写入CSV文件df.to_csv(\'output.csv\', index=False)# 写入Excel文件df.to_excel(\'output.xlsx\', index=False)

2.3 数据探索与清洗

查看数据

  1. df.head()

    df.head(n=5) # n: 要显示的前n行,默认为5
  2. df.tail()

    df.tail(n=5) # n: 要显示的后n行,默认为5
  3. df.info()

    df.info(verbose=None, buf=None, max_cols=None, memory_usage=None, show_counts=None) # 查看数据的基本信息
    • 参数 verbose:如果为 True,则打印完整的列信息。如果为 False,则打印简要的列信息。默认为 None,即自动选择。
    • 参数 buf:输出的目标,可以是 None(默认),表示输出到控制台;也可以指定一个文件对象,将输出写入该文件。
    • 参数 max_cols:指定显示的最大列数,默认为 None,即显示所有列。
    • 参数 memory_usage:是否显示内存使用情况。默认为 None,即自动选择。
    • 参数 show_counts:是否显示每列非空值的数量,默认为 None,即自动选择。
  4. df.describe()

    df.describe(percentiles=None, include=None, exclude=None) # 查看数据的统计摘要
    • 参数 percentiles:指定需要计算的百分位数。它是一个列表,默认计算常见的 25%50%(中位数)和 75% 百分位数。
    • 参数 include:指定要计算统计摘要的列类型。可以是 None(默认),表示所有列,或者指定如 [\'object\'](仅包括对象类型列)等类型。
    • 参数 exclude:指定不包含的列类型。默认是 None,表示不排除任何列。

处理缺失值

# 检查缺失值df.isnull().sum()# 删除包含缺失值的行df.dropna()# 填充缺失值df.fillna(value)

数据筛选

# 选择单列df[\'column_name\']# 选择多列df[[\'col1\', \'col2\']]# 条件筛选df[df[\'Age\'] > 30]# 使用loc和ilocdf.loc[row_indexer, column_indexer]df.iloc[row_position, column_position]

2.4 数据操作

1. 排序:

df.sort_values

【Python】数据处理工具:Pandas详细指南_pandas python

df.sort_values(by, axis=0, ascending=True, inplace=False, kind=\'quicksort\', na_position=\'last\', ignore_index=False, key=None) # 对数据进行排序
  • 参数 by:指定排序的列或列的列表。可以是单个列名(如 \'Age\')或者多个列名组成的列表(如 [\'Age\', \'Name\'])。
  • 参数 axis:指定排序的轴。默认值为 0,表示对行进行排序;如果设置为 1,则表示对列进行排序。
  • 参数 ascending:控制排序顺序。默认为 True,表示升序排列;False 则表示降序排列。如果 by 为多个列名,可以传入一个布尔列表,指定每列的排序顺序。
  • 参数 inplace:是否在原 DataFrame 上进行修改。默认为 False,返回排序后的新 DataFrame;如果设置为 True,则直接在原 DataFrame 上进行排序。
  • 参数 kind:指定排序算法。默认为 \'quicksort\',还可以选择 \'mergesort\'\'heapsort\' 等。
  • 参数 na_position:指定缺失值的位置。默认值为 \'last\',表示缺失值排在最后;可以设置为 \'first\',表示缺失值排在最前面。
  • 参数 ignore_index:是否重新生成索引。默认为 False,保留原有索引;设置为 True 时,会重新生成连续的整数索引。
  • 参数 key:传入一个函数,用于对排序列进行转换。例如,key=str.lower 会先将字符串列转换为小写字母后再排序。
代码示例

假设有一个名为 df 的 DataFrame,其中包含了员工的姓名、年龄和薪水信息:

import pandas as pd# 创建示例 DataFramedata = { \'Name\': [\'Alice\', \'Bob\', \'Charlie\', \'David\', \'Eve\'], \'Age\': [25, 30, 35, 40, 28], \'Salary\': [50000, 60000, 55000, 80000, 75000]}df = pd.DataFrame(data)print(\"原始 DataFrame:\")print(df)\'\'\'输出: Name Age Salary0 Alice 25 500001 Bob 30 600002 Charlie 35 550003 David 40 800004 Eve 28 75000\'\'\'

示例 1:按 Age 列升序排序

df_sorted = df.sort_values(by=\'Age\', ascending=True)print(\"\\n按 Age 升序排序:\")print(df_sorted)

输出:

 Name Age Salary0 Alice 25 500004 Eve 28 750001 Bob 30 600002 Charlie 35 550003 David 40 80000

2. 分组

df.groupby

【Python】数据处理工具:Pandas详细指南_pandas python

df.groupby(by, axis=0, level=None, as_index=True, sort=True, group_keys=True, squeeze=False, observed=False, dropna=True) # 对数据进行分组
  • 参数 by:指定用于分组的列名、列的列表或者字典。可以是单个列(如 \'Age\'),多个列(如 [\'Age\', \'Gender\'])或列名称到列值的映射(如 {\'Region\': \'Country\'})。
  • 参数 axis:指定要分组的轴,默认为 0,表示对行进行分组;如果为 1,则表示对列进行分组。
  • 参数 level:针对层次化索引(MultiIndex)进行分组,指定要按哪个层级进行分组,默认为 None,表示按所有列进行分组。
  • 参数 as_index:控制是否将分组的列作为返回 DataFrame 的索引。默认为 True,即分组列成为索引;如果为 False,分组列会作为普通列返回。
  • 参数 sort:是否按分组键进行排序。默认为 True,表示按分组键排序;如果为 False,则按原始顺序返回分组。
  • 参数 group_keys:是否保留分组键。默认为 True,即会保留分组键作为结果的一部分;如果为 False,则只返回结果。
  • 参数 squeeze:如果分组结果是单列或单行,是否返回一个 Series 而不是 DataFrame。默认为 False
  • 参数 observed:在分组时,是否仅考虑实际出现的类别。默认为 False,即包括所有类别;如果为 True,则仅包括在数据中实际出现的类别。
  • 参数 dropna:是否排除缺失值。默认为 True,即排除缺失值所在的组;如果为 False,则保留缺失值所在的组。

groupby 允许我们根据某些列的值对数据进行分组,然后对每个组进行聚合操作(如求平均值、求和等)。可以对分组后的数据执行多种统计操作,非常灵活。

代码示例

假设有一个名为 df 的 DataFrame,包含员工的部门和薪水信息,想要按部门计算薪水的平均值:

import pandas as pd# 创建示例 DataFramedata = { \'Department\': [\'HR\', \'Engineering\', \'Engineering\', \'HR\', \'Sales\'], \'Salary\': [50000, 70000, 75000, 52000, 60000]}df = pd.DataFrame(data)# 按部门进行分组,并计算薪水的平均值grouped = df.groupby(\'Department\')[\'Salary\'].mean()print(grouped)

输出:

DepartmentEngineering 72500.0HR 51000.0Sales 60000.0Name: Salary, dtype: float64

在这个示例中,我们使用 groupbyDepartment 列进行分组,并计算每个部门的平均薪水。


3. 合并数据

pd.concat

【Python】数据处理工具:Pandas详细指南_pandas python

pd.concat(objs, axis=0, join=\'outer\', ignore_index=False, keys=None, levels=None, names=None, verify_integrity=False, sort=False, copy=True)
  • 参数 objs:一个可迭代的对象(如列表、元组等),包含多个 DataFrame 或 Series 要合并的对象。
  • 参数 axis:指定沿着哪个轴进行合并。默认为 0,表示按行合并(垂直拼接);如果为 1,表示按列合并(水平拼接)。
  • 参数 join:指定合并时的连接方式。\'outer\'(默认)表示并集;\'inner\' 表示交集,只保留两个 DataFrame 都有的索引/列。
  • 参数 ignore_index:是否重置索引。默认为 False,即保留原索引;如果为 True,则会重新生成索引。
  • 参数 keys:用于在合并的结果中创建层次化索引,可以传入一个序列来为每个 DataFrame 指定一个键。
  • 参数 levels:指定层次化索引的级别。
  • 参数 names:指定层次化索引的名称。
  • 参数 verify_integrity:是否检查合并后的数据是否存在重复的索引。默认为 False,即不检查;如果为 True,会抛出错误。
  • 参数 sort:合并时是否对列进行排序。默认为 False,即不排序;如果为 True,则会按字母顺序排序。
  • 参数 copy:是否复制数据。默认为 True,即复制数据;如果为 False,则会尽量避免复制数据。
使用示例:按行合并 DataFrame
import pandas as pd# 创建示例 DataFramedata1 = { \'Name\': [\'Alice\', \'Bob\'], \'Age\': [25, 30]}data2 = { \'Name\': [\'Charlie\', \'David\'], \'Age\': [35, 40]}df1 = pd.DataFrame(data1)df2 = pd.DataFrame(data2)# 合并两个 DataFrame(按行合并)result = pd.concat([df1, df2], ignore_index=True)print(result)

输出:

 Name Age0 Alice 251 Bob 302 Charlie 353 David 40

在此示例中,df1df2 被按行合并,且重置了索引。

pd.merge

【Python】数据处理工具:Pandas详细指南_pandas python

pd.merge(left, right, how=\'inner\', on=None, left_on=None, right_on=None, left_index=False, right_index=False, sort=True, suffixes=(\'_x\', \'_y\'), copy=True, indicator=False, validate=None)
  • 参数 leftright:要合并的两个 DataFrame。
  • 参数 how:指定合并的方式。常见的选项有:
  • \'inner\'(默认):取交集,只保留在两个 DataFrame 中都存在的行。
  • \'outer\':取并集,保留两个 DataFrame 中所有的行。
  • \'left\':只保留左侧 DataFrame 中的行。
  • \'right\':只保留右侧 DataFrame 中的行。
  • 参数 on:指定合并时的列名,默认为 None,表示在两个 DataFrame 中都有的列名上进行合并。
  • 参数 left_onright_on:指定分别用于左侧和右侧 DataFrame 合并的列名。如果 onNone,可以通过这两个参数单独指定。
  • 参数 left_indexright_index:是否使用索引进行合并。默认为 False,如果为 True,则使用索引进行合并。
  • 参数 sort:是否对合并后的数据按键进行排序。默认为 True,即按键排序;如果为 False,则不排序。
  • 参数 suffixes:为重复列添加后缀。默认为 (\'_x\', \'_y\')
  • 参数 indicator:是否添加一列指示信息,显示每行数据来自哪个 DataFrame。默认为 False,如果为 True,会添加一个名为 _merge 的列。
  • 参数 validate:用于数据完整性检查的参数,常见选项有 \'one_to_one\', \'one_to_many\', \'many_to_one\', \'many_to_many\'
使用示例:SQL风格的合并
import pandas as pd# 创建示例 DataFramedata1 = { \'ID\': [1, 2, 3], \'Name\': [\'Alice\', \'Bob\', \'Charlie\']}data2 = { \'ID\': [2, 3, 4], \'Salary\': [50000, 60000, 70000]}df1 = pd.DataFrame(data1)df2 = pd.DataFrame(data2)# 按 \'ID\' 列合并两个 DataFrame(内连接)result = pd.merge(df1, df2, on=\'ID\', how=\'inner\')print(result)

输出:

 ID Name Salary0 2 Bob 500001 3 Charlie 60000

在这个例子中,df1df2 按照 ID 列进行 SQL 风格的合并,只保留在两个 DataFrame 中都存在的 ID 值。


4. 应用函数

series.apply

【Python】数据处理工具:Pandas详细指南_pandas python

Series.apply(func, convert_dtype=True, args=(), **kwds)
  • 参数 func:要应用到每个元素的函数(或函数名)。在这个例子中,lambda x: x * 2 是将每个 Age 列的元素都乘以 2。
  • 参数 convert_dtype:是否转换返回的结果类型。默认为 True,即转换为适当的类型;如果为 False,则保留原始类型。
  • 参数 args:传递给 func 的额外位置参数。
  • 参数 **kwds:传递给 func 的额外关键字参数。
使用示例:将 Age 列的值乘以 2
import pandas as pd# 创建示例 DataFramedata = { \'Name\': [\'Alice\', \'Bob\', \'Charlie\'], \'Age\': [25, 30, 35], \'Weight\': [55, 65, 75]}df = pd.DataFrame(data)# 使用 apply 将 Age 列的每个元素乘以 2df[\'Age_doubled\'] = df[\'Age\'].apply(lambda x: x * 2)print(df)

输出:

 Name Age Weight Age_doubled0 Alice 25 55 501 Bob 30 65 602 Charlie 35 75 70

在这个例子中,我们使用 applyAge 列的每个元素应用了 lambda x: x * 2 的函数,使得每个 Age 值都被乘以了 2。

df.apply

【Python】数据处理工具:Pandas详细指南_pandas python

DataFrame.apply(func, axis=0, raw=False, result_type=None, args=(), **kwds)
  • 参数 func:要应用的函数(或函数名)。在这个例子中,lambda row: row[\'Age\'] * row[\'Weight\'] 是对每一行执行计算,即将 AgeWeight 两列相乘。
  • 参数 axis:指定操作的轴。axis=0 表示按列应用函数(默认);axis=1 表示按行应用函数。在这个例子中,axis=1 使得我们在每行上应用函数。
  • 参数 raw:是否传递原始数据给函数。如果为 True,则传递原始数组给函数,而不是 Series。
  • 参数 result_type:指定返回结果的类型。可以是 expand(展开为 DataFrame),reduce(返回 Series),或者 broadcast(广播到原始 DataFrame 形状)。
  • 参数 args:传递给 func 的额外位置参数。
  • 参数 **kwds:传递给 func 的额外关键字参数。
使用示例:按行计算 AgeWeight 的乘积
import pandas as pd# 创建示例 DataFramedata = { \'Name\': [\'Alice\', \'Bob\', \'Charlie\'], \'Age\': [25, 30, 35], \'Weight\': [55, 65, 75]}df = pd.DataFrame(data)# 使用 apply 对每行进行计算,得到 Age 和 Weight 的乘积df[\'Age_Weight\'] = df.apply(lambda row: row[\'Age\'] * row[\'Weight\'], axis=1)print(df)

输出:

 Name Age Weight Age_Weight0 Alice 25 55 13751 Bob 30 65 19502 Charlie 35 75 2625

在这个例子中,我们使用 apply 对每一行应用了 lambda row: row[\'Age\'] * row[\'Weight\'] 的函数,使得每行的 AgeWeight 列的乘积被计算并添加为新的一列 Age_Weight


2.5 时间序列处理

Pandas对时间序列数据有出色的支持:

# 创建时间序列date_rng = pd.date_range(start=\'1/1/2020\', end=\'1/08/2020\', freq=\'D\')# 设置索引为日期df.set_index(\'date_column\', inplace=True)# 重采样df.resample(\'M\').mean()

2.6 数据可视化

Pandas集成了Matplotlib,可以轻松绘制图表:

# 线图df.plot()# 柱状图df.plot.bar()# 直方图df[\'Age\'].plot.hist()# 箱线图df.plot.box()

2.7 性能优化技巧

  1. 使用适当的数据类型(如category类型用于分类变量)
  2. 避免循环,使用向量化操作
  3. 使用query()方法进行高效查询
  4. 对于大型数据集,考虑使用Dask或Modin等扩展库

三、代码示例

示例1:销售数据分析

# 读取销售数据sales = pd.read_csv(\'sales_data.csv\')# 计算每月销售额sales[\'date\'] = pd.to_datetime(sales[\'date\'])monthly_sales = sales.resample(\'M\', on=\'date\')[\'amount\'].sum()# 可视化monthly_sales.plot(title=\'Monthly Sales\')

示例2:客户细分

# 创建RFM指标snapshot_date = max(df[\'InvoiceDate\']) + pd.Timedelta(days=1)rfm = df.groupby(\'CustomerID\').agg({ \'InvoiceDate\': lambda x: (snapshot_date - x.max()).days, \'InvoiceNo\': \'count\', \'TotalPrice\': \'sum\'})# 重命名列rfm.rename(columns={ \'InvoiceDate\': \'Recency\', \'InvoiceNo\': \'Frequency\', \'TotalPrice\': \'MonetaryValue\'}, inplace=True)