文章目录
- 一、前言
-
- [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 数据操作)
-
- [1. 排序:](#1. 排序:)
- [2. 分组](#2. 分组)
- [3. 合并数据](#3. 合并数据)
-
- pd.concat
- [使用示例:按行合并 DataFrame](#使用示例:按行合并 DataFrame)
- pd.merge
- 使用示例:SQL风格的合并
- [4. 应用函数](#4. 应用函数)
-
- series.apply
- [使用示例:将 `Age` 列的值乘以 2](#使用示例:将
Age
列的值乘以 2) - df.apply
- [使用示例:按行计算 `Age` 和 `Weight` 的乘积](#使用示例:按行计算
Age
和Weight
的乘积)
- [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的使用与相关接口进行介绍,很多接口的参数较多与复杂,这里只对部分进行解释,感兴趣的话可以去看官方文档:
1.2 安装Pandas
在开始使用Pandas之前,需要先安装它。直接通过pip安装即可:
bash
pip install pandas
# 如果使用Anaconda发行版
conda install pandas
二、Pandas 数据相关
2.1 Pandas核心数据结构
Pandas有两个主要的数据结构:Series
和DataFrame
。
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 数据探索与清洗
查看数据
-
df.head()
pythondf.head(n=5) # n: 要显示的前n行,默认为5
-
df.tail()
pythondf.tail(n=5) # n: 要显示的后n行,默认为5
-
df.info()
pythondf.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
,即自动选择。
- 参数
-
df.describe()
pythondf.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
在这个示例中,我们使用 groupby
按 Department
列进行分组,并计算每个部门的平均薪水。
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
在此示例中,df1
和 df2
被按行合并,且重置了索引。
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)
- 参数
left
和right
:要合并的两个 DataFrame。- 参数
how
:指定合并的方式。常见的选项有:
'inner'
(默认):取交集,只保留在两个 DataFrame 中都存在的行。'outer'
:取并集,保留两个 DataFrame 中所有的行。'left'
:只保留左侧 DataFrame 中的行。'right'
:只保留右侧 DataFrame 中的行。
- 参数
on
:指定合并时的列名,默认为None
,表示在两个 DataFrame 中都有的列名上进行合并。- 参数
left_on
和right_on
:指定分别用于左侧和右侧 DataFrame 合并的列名。如果on
为None
,可以通过这两个参数单独指定。- 参数
left_index
和right_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
在这个例子中,df1
和 df2
按照 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
在这个例子中,我们使用 apply
对 Age
列的每个元素应用了 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']
是对每一行执行计算,即将Age
和Weight
两列相乘。- 参数
axis
:指定操作的轴。axis=0
表示按列应用函数(默认);axis=1
表示按行应用函数。在这个例子中,axis=1
使得我们在每行上应用函数。- 参数
raw
:是否传递原始数据给函数。如果为True
,则传递原始数组给函数,而不是 Series。- 参数
result_type
:指定返回结果的类型。可以是expand
(展开为 DataFrame),reduce
(返回 Series),或者broadcast
(广播到原始 DataFrame 形状)。- 参数
args
:传递给func
的额外位置参数。- 参数
**kwds
:传递给func
的额外关键字参数。
使用示例:按行计算 Age
和 Weight
的乘积
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']
的函数,使得每行的 Age
和 Weight
列的乘积被计算并添加为新的一列 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 性能优化技巧
- 使用适当的数据类型(如category类型用于分类变量)
- 避免循环,使用向量化操作
- 使用query()方法进行高效查询
- 对于大型数据集,考虑使用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)