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

文章目录

  • 一、前言
    • [1.1 什么是Pandas?](#1.1 什么是Pandas?)
    • [1.2 安装Pandas](#1.2 安装Pandas)
  • [二、Pandas 数据相关](#二、Pandas 数据相关)
    • [2.1 Pandas核心数据结构](#2.1 Pandas核心数据结构)
      • [1. Series](#1. Series)
      • [2. DataFrame](#2. DataFrame)
    • [2.2 数据读取与写入](#2.2 数据读取与写入)
    • [2.3 数据探索与清洗](#2.3 数据探索与清洗)
    • [2.4 数据操作](#2.4 数据操作)
    • [2.5 时间序列处理](#2.5 时间序列处理)
    • [2.6 数据可视化](#2.6 数据可视化)
    • [2.7 性能优化技巧](#2.7 性能优化技巧)
  • 三、代码示例

一、前言

1.1 什么是Pandas?

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

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

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

pandas documentation


1.2 安装Pandas

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

bash 复制代码
pip install pandas
# 如果使用Anaconda发行版
conda install pandas

二、Pandas 数据相关

2.1 Pandas核心数据结构

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

1. Series

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

python 复制代码
import pandas as pd

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

输出结果:

bash 复制代码
0    1
1    3
2    5
3    7
4    9
dtype: int64

2. DataFrame

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

python 复制代码
# 创建一个DataFrame
data = {
    'Name': ['Alice', 'Bob', 'Charlie', 'David'],
    'Age': [25, 30, 35, 40],
    'City': ['New York', 'Paris', 'London', 'Tokyo']
}

df = pd.DataFrame(data)
print(df)

输出结果:

bash 复制代码
      Name  Age      City
0    Alice   25  New York
1      Bob   30     Paris
2  Charlie   35    London
3    David   40     Tokyo

2.2 数据读取与写入

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

python 复制代码
# 读取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()

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

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

    python 复制代码
    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()

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

处理缺失值

python 复制代码
# 检查缺失值
df.isnull().sum()

# 删除包含缺失值的行
df.dropna()

# 填充缺失值
df.fillna(value)

数据筛选

python 复制代码
# 选择单列
df['column_name']

# 选择多列
df[['col1', 'col2']]

# 条件筛选
df[df['Age'] > 30]

# 使用loc和iloc
df.loc[row_indexer, column_indexer]
df.iloc[row_position, column_position]

2.4 数据操作

1. 排序:

df.sort_values
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,其中包含了员工的姓名、年龄和薪水信息:

python 复制代码
import pandas as pd

# 创建示例 DataFrame
data = {
    '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  Salary
0   Alice   25   50000
1     Bob   30   60000
2  Charlie   35   55000
3   David   40   80000
4     Eve   28   75000
'''

示例 1:按 Age 列升序排序

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

输出:

bash 复制代码
     Name  Age  Salary
0   Alice   25   50000
4     Eve   28   75000
1     Bob   30   60000
2  Charlie   35   55000
3   David   40   80000

2. 分组

df.groupby
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,包含员工的部门和薪水信息,想要按部门计算薪水的平均值:

python 复制代码
import pandas as pd

# 创建示例 DataFrame
data = {
    'Department': ['HR', 'Engineering', 'Engineering', 'HR', 'Sales'],
    'Salary': [50000, 70000, 75000, 52000, 60000]
}

df = pd.DataFrame(data)

# 按部门进行分组,并计算薪水的平均值
grouped = df.groupby('Department')['Salary'].mean()

print(grouped)

输出:

bash 复制代码
Department
Engineering    72500.0
HR             51000.0
Sales          60000.0
Name: Salary, dtype: float64

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


3. 合并数据

pd.concat
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
python 复制代码
import pandas as pd

# 创建示例 DataFrame
data1 = {
    '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  Age
0    Alice   25
1      Bob   30
2  Charlie   35
3    David   40

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

pd.merge
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风格的合并
python 复制代码
import pandas as pd

# 创建示例 DataFrame
data1 = {
    '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  Salary
0   2      Bob   50000
1   3  Charlie   60000

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


4. 应用函数

series.apply
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
python 复制代码
import pandas as pd

# 创建示例 DataFrame
data = {
    'Name': ['Alice', 'Bob', 'Charlie'],
    'Age': [25, 30, 35],
    'Weight': [55, 65, 75]
}
df = pd.DataFrame(data)

# 使用 apply 将 Age 列的每个元素乘以 2
df['Age_doubled'] = df['Age'].apply(lambda x: x * 2)

print(df)

输出:

复制代码
      Name  Age  Weight  Age_doubled
0    Alice   25      55          50
1      Bob   30      65          60
2  Charlie   35      75          70

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

df.apply
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 的乘积
python 复制代码
import pandas as pd

# 创建示例 DataFrame
data = {
    '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)

输出:

bash 复制代码
      Name  Age  Weight  Age_Weight
0    Alice   25      55        1375
1      Bob   30      65        1950
2  Charlie   35      75        2625

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


2.5 时间序列处理

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

python 复制代码
# 创建时间序列
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,可以轻松绘制图表:

python 复制代码
# 线图
df.plot()

# 柱状图
df.plot.bar()

# 直方图
df['Age'].plot.hist()

# 箱线图
df.plot.box()

2.7 性能优化技巧

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

三、代码示例

示例1:销售数据分析

python 复制代码
# 读取销售数据
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:客户细分

python 复制代码
# 创建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)
相关推荐
wu_android几秒前
Java匿名内部类访问全局变量和局部变量的注意事项
java·开发语言
ajassi20003 分钟前
开源 python 应用 开发(二)基于pyautogui、open cv 视觉识别的工具自动化
python·opencv·开源·自动化
Zevalin爱灰灰8 分钟前
MATLAB GUI界面设计 第二章——APP Designer操作正式入门
开发语言·ui·matlab
uwvwko14 分钟前
数据结构学习——树的储存结构
数据库·学习·算法·
程序员弘羽15 分钟前
C++ 第二阶段:类与对象 - 第三节:成员函数与访问权限
开发语言·c++
我命由我1234538 分钟前
C++ - 标准库之 <string> npos(npos 概述、npos 的作用)
服务器·c语言·开发语言·c++·后端·visualstudio·visual studio
君鼎41 分钟前
C++项目经验与解决问题能力需知
开发语言·c++
Ethan30141 小时前
Clickhouse官方文档学习笔记
笔记·学习·clickhouse
IT艺术家-rookie1 小时前
golang--数据类型与存储
开发语言·后端·golang
小幽余生不加糖1 小时前
反无人机系统:技术利刃如何守护低空安全?
笔记·学习·安全·无人机