目录
一、Pandas 简介
Pandas 是一个开源的 Python 数据分析库,由 Wes McKinney 于 2008 年创建。它的名字来源于 “panel data”(面板数据),这是一种在经济学中常用的多维数据类型。Pandas 的目标是为 Python 提供一个功能强大、灵活易用的数据结构和数据分析工具,以满足现实世界中复杂多样的数据处理需求。
Pandas 的核心优势在于其两大主要数据结构:Series
和 DataFrame
。Series
是一个一维的标签化数组,而 DataFrame
则是一个二维的表格型数据结构,类似于 Excel 中的表格或 SQL 中的表。这些数据结构使得数据的存储、检索、操作和分析变得更加直观和高效。
二、Pandas 的安装与导入
要使用 Pandas,首先需要确保它已正确安装在你的 Python 环境中。可以通过以下方式进行安装:
-
使用 pip 安装 :在命令行中输入 “pip install pandas”,pip 会自动下载并安装 Pandas 及其依赖项。
-
使用 conda 安装 :如果你使用 Anaconda 发行版,可以在命令行中输入 “conda install pandas”,conda 会从其仓库中安装合适的 Pandas 版本。
安装完成后,在 Python 脚本或交互式环境中,通过以下代码导入 Pandas:
import pandas as pd
通常我们使用 “pd” 作为 Pandas 的别名,这样在后续代码中可以更简洁地调用 Pandas 的函数和类。
三、Pandas 的核心数据结构
(一)Series
Series
是 Pandas 中的一维数据结构,类似于 NumPy 的一维数组,但带有标签。这些标签可以是任何类型,如整数、字符串等,它们为数据提供了更直观的索引方式。
创建 Series
的基本方法如下
import pandas as pd
# 从列表创建 Series
data = [10, 20, 30, 40, 50]
s = pd.Series(data)
print(s)
0 10
1 20
2 30
3 40
4 50
dtype: int64
默认情况下,Series
的索引是从 0 开始的整数序列。你也可以自定义索引:
import pandas as pd
# 从列表创建 Series 并自定义索引
data = [10, 20, 30, 40, 50]
index = ['a', 'b', 'c', 'd', 'e']
s = pd.Series(data, index=index)
print(s)
a 10
b 20
c 30
d 40
e 50
dtype: int64
访问 Series
中的元素可以通过索引标签或位置:
# 通过索引标签访问元素
print(s['b']) # 输出 20
# 通过位置访问元素
print(s[2]) # 输出 30
(二)DataFrame
DataFrame
是 Pandas 中的二维数据结构,类似于表格,包含行和列。它是 Pandas 最常用的数据结构之一,适合存储和处理结构化数据。
创建 DataFrame
的基本方法如下:
import pandas as pd
# 从字典创建 DataFrame
data = {
'Name': ['Alice', 'Bob', 'Charlie', 'David'],
'Age': [25, 30, 35, 40],
'City': ['New York', 'Los Angeles', 'Chicago', 'Houston']
}
df = pd.DataFrame(data)
print(df)
Name Age City
0 Alice 25 New York
1 Bob 30 Los Angeles
2 Charlie 35 Chicago
3 David 40 Houston
DataFrame
的列可以通过列名进行访问和操作
# 访问某一列
print(df['Name'])
0 Alice
1 Bob
2 Charlie
3 David
Name: Name, dtype: object
你也可以同时访问多列:
# 访问多列
print(df[['Name', 'Age']])
Name Age
0 Alice 25
1 Bob 30
2 Charlie 35
3 David 40
DataFrame
的行可以通过 iloc
(基于整数位置索引)或 loc
(基于标签索引)进行访问:
# 通过 iloc 访问第 2 行
print(df.iloc[2])
Name Charlie
Age 35
City Chicago
Name: 2, dtype: object
# 通过 loc 访问索引标签为 1 的行
print(df.loc[1])
输出结果:
Name Bob
Age 30
City Los Angeles
Name: 1, dtype: object
四、Pandas 数据读取与写入
Pandas 提供了丰富的函数用于读取和写入各种格式的数据,如 CSV、Excel、SQL 数据库等。
(一)读取数据
-
读取 CSV 文件 :
import pandas as pd
# 读取 CSV 文件
df = pd.read_csv('data.csv')
print(df.head()) # 显示前 5 行数据
-
读取 Excel 文件 :
import pandas as pd
# 读取 Excel 文件
df = pd.read_excel('data.xlsx', sheet_name='Sheet1')
print(df.head())
-
从 SQL 数据库读取数据 :
import pandas as pd
import sqlite3
# 连接到 SQLite 数据库
conn = sqlite3.connect('database.db')
# 从数据库读取数据
df = pd.read_sql_query('SELECT * FROM table_name', conn)
print(df.head())
# 关闭数据库连接
conn.close()
(二)写入数据
-
写入 CSV 文件 :
import pandas as pd
# 创建 DataFrame
data = {
'Name': ['Alice', 'Bob', 'Charlie', 'David'],
'Age': [25, 30, 35, 40],
'City': ['New York', 'Los Angeles', 'Chicago', 'Houston']
}
df = pd.DataFrame(data)
# 将 DataFrame 写入 CSV 文件
df.to_csv('output.csv', index=False)
-
写入 Excel 文件 :
import pandas as pd
# 创建 DataFrame
data = {
'Name': ['Alice', 'Bob', 'Charlie', 'David'],
'Age': [25, 30, 35, 40],
'City': ['New York', 'Los Angeles', 'Chicago', 'Houston']
}
df = pd.DataFrame(data)
# 将 DataFrame 写入 Excel 文件
df.to_excel('output.xlsx', sheet_name='Sheet1', index=False)
-
写入 SQL 数据库 :
import pandas as pd
import sqlite3
# 创建 DataFrame
data = {
'Name': ['Alice', 'Bob', 'Charlie', 'David'],
'Age': [25, 30, 35, 40],
'City': ['New York', 'Los Angeles', 'Chicago', 'Houston']
}
df = pd.DataFrame(data)
# 连接到 SQLite 数据库
conn = sqlite3.connect('database.db')
# 将 DataFrame 写入数据库
df.to_sql('table_name', conn, if_exists='replace', index=False)
# 关闭数据库连接
conn.close()
五、数据清洗与预处理
在实际数据分析中,数据往往不完整、不一致或包含错误,需要进行清洗和预处理,以确保数据的质量。Pandas 提供了许多工具来帮助完成这些任务。
(一)处理缺失值
缺失值是数据清洗中常见的问题,Pandas 提供了检测、删除和填充缺失值的函数。
-
检测缺失值 :
import pandas as pd
# 创建包含缺失值的 DataFrame
data = {
'A': [1, 2, None, 4],
'B': [5, None, 7, 8],
'C': [9, 10, 11, None]
}
df = pd.DataFrame(data)
# 检测缺失值
print(df.isnull())
输出结果:
A B C
0 False False False
1 False True False
2 True False False
3 False False True
-
删除缺失值 :
# 删除包含缺失值的行
df.dropna(inplace=True)
print(df)
-
填充缺失值 :
# 用 0 填充缺失值
df.fillna(0, inplace=True)
print(df)
(二)数据去重
重复数据可能导致分析结果的偏差,Pandas 提供了检测和删除重复数据的功能。
-
检测重复数据 :
import pandas as pd
# 创建包含重复数据的 DataFrame
data = {
'A': [1, 2, 2, 4],
'B': [5, 6, 6, 8],
'C': [9, 10, 10, 12]
}
df = pd.DataFrame(data)
# 检测重复行
print(df.duplicated())
0 False
1 False
2 True
3 False
dtype: bool
-
删除重复数据 :
# 删除重复行
df.drop_duplicates(inplace=True)
print(df)
(三)数据转换
数据转换是将数据从一种形式转换为另一种形式的过程,包括数据类型转换、数值缩放、编码等。
-
数据类型转换 :
import pandas as pd
# 创建 DataFrame
data = {
'A': [1, 2, 3, 4],
'B': [5.0, 6.5, 7.2, 8.9],
'C': ['apple', 'banana', 'orange', 'grape']
}
df = pd.DataFrame(data)
# 将列 A 转换为浮点型
df['A'] = df['A'].astype(float)
# 将列 B 转换为整型(向下取整)
df['B'] = df['B'].astype(int)
print(df.dtypes)
输出结果:
A float64
B int32
C object
dtype: object
-
数值缩放 :
import pandas as pd
# 创建 DataFrame
data = {
'A': [10, 20, 30, 40, 50]
}
df = pd.DataFrame(data)
# 使用 Min-Max 缩放将数据缩放到 [0, 1] 范围
df['A'] = (df['A'] - df['A'].min()) / (df['A'].max() - df['A'].min())
print(df)
输出结果:
A
0 0.0
1 0.25
2 0.5
3 0.75
4 1.0
-
编码分类数据 :
import pandas as pd
# 创建包含分类数据的 DataFrame
data = {
'Color': ['Red', 'Blue', 'Green', 'Red', 'Blue']
}
df = pd.DataFrame(data)
# 使用 one-hot 编码转换分类数据
df = pd.get_dummies(df, columns=['Color'])
print(df)
输出结果:
Color_Blue Color_Green Color_Red
0 0 0 1
1 1 0 0
2 0 1 0
3 0 0 1
4 1 0 0
(四)数据合并与连接
在数据分析中,通常需要将多个数据集合并成一个,Pandas 提供了多种方法来实现数据的合并和连接。
-
合并数据集 :
import pandas as pd
# 创建两个 DataFrame
data1 = {
'Key': ['A', 'B', 'C', 'D'],
'Value1': [10, 20, 30, 40]
}
df1 = pd.DataFrame(data1)
data2 = {
'Key': ['B', 'D', 'E', 'F'],
'Value2': [50, 60, 70, 80]
}
df2 = pd.DataFrame(data2)
# 基于 'Key' 列合并两个 DataFrame
merged_df = pd.merge(df1, df2, on='Key', how='inner')
print(merged_df)
输出结果:
Key Value1 Value2
0 B 20 50
1 D 40 60
how
参数可以取以下值:
-
inner
:内连接(默认),只保留两个数据集中共有的键。 -
outer
:外连接,保留两个数据集中的所有键,缺失值用 NaN 填充。 -
left
:左连接,保留左数据集中的所有键,右数据集中缺失的键用 NaN 填充。 -
right
:右连接,保留右数据集中的所有键,左数据集中缺失的键用 NaN 填充。 -
连接数据集 :
import pandas as pd
# 创建两个 DataFrame
data1 = {
'A': [1, 2, 3],
'B': [4, 5, 6]
}
df1 = pd.DataFrame(data1, index=['X', 'Y', 'Z'])
data2 = {
'C': [7, 8, 9],
'D': [10, 11, 12]
}
df2 = pd.DataFrame(data2, index=['Y', 'Z', 'W'])
# 按行连接两个 DataFrame
concatenated_df = pd.concat([df1, df2], axis=0)
print(concatenated_df)
输出结果:
A B C D
X 1.0 4.0 NaN NaN
Y 2.0 5.0 7.0 10.0
Z 3.0 6.0 8.0 11.0
W NaN NaN 9.0 12.0
axis
参数指定连接的方向,axis=0
表示按行连接,axis=1
表示按列连接。
六、数据探索与分析
Pandas 提供了丰富的函数用于数据的探索和分析,帮助你快速了解数据的基本特征和统计信息。
(一)数据概览
-
查看前几行数据 :
import pandas as pd
# 创建 DataFrame
data = {
'Name': ['Alice', 'Bob', 'Charlie', 'David'],
'Age': [25, 30, 35, 40],
'City': ['New York', 'Los Angeles', 'Chicago', 'Houston']
}
df = pd.DataFrame(data)
# 查看前 3 行数据
print(df.head(3))
输出结果:
Name Age City
0 Alice 25 New York
1 Bob 30 Los Angeles
2 Charlie 35 Chicago
-
查看数据的基本信息 :
# 查看数据的基本信息
df.info()
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 4 entries, 0 to 3
Data columns (total 3 columns):
# Column Non-Null Count Dtype
--- ------ -------------- -----
0 Name 4 non-null object
1 Age 4 non-null int64
2 City 4 non-null object
dtypes: int64(1), object(2)
memory usage: 208.0+ bytes
-
查看数据的统计摘要 :
# 查看数据的统计摘要
print(df.describe())
Age
count 4.000000
mean 32.500000
std 6.454972
min 25.000000
25% 28.750000
50% 32.500000
75% 36.250000
max 40.000000
(二)数据分组与聚合
数据分组与聚合是数据分析中的常见操作,Pandas 提供了方便的 groupby
和聚合函数来实现这些功能。
-
按某一列分组并求和 :
import pandas as pd
# 创建 DataFrame
data = {
'Category': ['A', 'B', 'A', 'B', 'A', 'B'],
'Value': [10, 20, 30, 40, 50, 60]
}
df = pd.DataFrame(data)
# 按 'Category' 列分组,并对 'Value' 列求和
grouped_df = df.groupby('Category')['Value'].sum()
print(grouped_df)
Category
A 90
B 120
Name: Value, dtype: int64
-
按多列分组并计算多种聚合统计量 :
import pandas as pd
# 创建 DataFrame
data = {
'Category': ['A', 'B', 'A', 'B', 'A', 'B'],
'Subcategory': ['X', 'Y', 'X', 'Y', 'X', 'Y'],
'Value': [10, 20, 30, 40, 50, 60]
}
df = pd.DataFrame(data)
# 按 'Category' 和 'Subcategory' 列分组,并计算 'Value' 列的均值和总和
grouped_df = df.groupby(['Category', 'Subcategory'])['Value'].agg(['mean', 'sum'])
print(grouped_df)
mean sum
Category Subcategory
A X 30 90
B Y 40 120
(三)数据筛选与排序
-
数据筛选 :
import pandas as pd
# 创建 DataFrame
data = {
'Name': ['Alice', 'Bob', 'Charlie', 'David', 'Eve'],
'Age': [25, 30, 35, 40, 28],
'City': ['New York', 'Los Angeles', 'Chicago', 'Houston', 'Seattle']
}
df = pd.DataFrame(data)
# 筛选年龄大于 30 的行
filtered_df = df[df['Age'] > 30]
print(filtered_df)
Name Age City
2 Charlie 35 Chicago
3 David 40 Houston
-
数据排序 :
# 按年龄降序排序
sorted_df = df.sort_values(by='Age', ascending=False)
print(sorted_df)
Name Age City
3 David 40 Houston
2 Charlie 35 Chicago
1 Bob 30 Los Angeles
4 Eve 28 Seattle
0 Alice 25 New York
七、Pandas 的实际应用案例
(一)金融数据分析
假设我们有一个股票价格数据集,包含日期、开盘价、收盘价、最高价、最低价和成交量等信息。我们可以使用 Pandas 对这些数据进行分析。
import pandas as pd
# 读取股票价格数据
df = pd.read_csv('stock_prices.csv')
# 转换日期列为日期时间类型
df['Date'] = pd.to_datetime(df['Date'])
# 将日期列设置为索引
df.set_index('Date', inplace=True)
# 计算每日收益率
df['Return'] = df['Close'].pct_change() * 100
# 绘制收盘价和收益率图
import matplotlib.pyplot as plt
fig, ax1 = plt.subplots()
ax1.plot(df['Close'], label='Close Price', color='blue')
ax1.set_xlabel('Date')
ax1.set_ylabel('Close Price', color='blue')
ax1.tick_params(axis='y', labelcolor='blue')
ax2 = ax1.twinx()
ax2.plot(df['Return'], label='Daily Return', color='red', linestyle='--')
ax2.set_ylabel('Daily Return (%)', color='red')
ax2.tick_params(axis='y', labelcolor='red')
plt.title('Stock Price and Daily Return')
fig.tight_layout()
plt.show()
(二)销售数据分析
假设我们有一个销售数据集,包含产品名称、销售日期、销售数量、销售价格等信息。我们可以使用 Pandas 分析产品的销售趋势和收益情况。
import pandas as pd
# 读取销售数据
df = pd.read_csv('sales_data.csv')
# 转换销售日期列为日期时间类型
df['Sale Date'] = pd.to_datetime(df['Sale Date'])
# 按月统计销售数量和销售额
monthly_sales = df.resample('M', on='Sale Date').agg({
'Quantity': 'sum',
'Price': 'sum'
})
monthly_sales.columns = ['Total Quantity', 'Total Sales']
# 绘制月度销售趋势图
import matplotlib.pyplot as plt
monthly_sales.plot(kind='line', secondary_y='Total Sales')
plt.title('Monthly Sales Trend')
plt.xlabel('Month')
plt.ylabel('Total Quantity')
plt.gcf().axes[1].set_ylabel('Total Sales')
plt.tight_layout()
plt.show()
八、Pandas 的高级特性
(一)时间序列分析
Pandas 提供了强大的时间序列处理功能,包括日期范围生成、时间索引操作、时间序列重采样等。
-
生成日期范围 :
import pandas as pd
# 生成从 2023-01-01 到 2023-12-31 的日期范围
date_range = pd.date_range(start='2023-01-01', end='2023-12-31', freq='D')
print(date_range)
-
时间序列重采样 :
import pandas as pd
# 创建时间序列数据
index = pd.date_range(start='2023-01-01', periods=100, freq='D')
data = np.random.randn(100)
ts = pd.Series(data, index=index)
# 按周重采样并计算周平均值
weekly_mean = ts.resample('W').mean()
print(weekly_mean)
(二)高级数据透视表
数据透视表是一种用于数据汇总和分析的强大工具,Pandas 提供了灵活的 pivot_table
函数来创建数据透视表。
import pandas as pd
# 创建示例数据
data = {
'Product': ['A', 'B', 'A', 'B', 'A', 'B'],
'Category': ['X', 'X', 'Y', 'Y', 'X', 'Y'],
'Region': ['North', 'South', 'East', 'West', 'North', 'South'],
'Sales': [100, 150, 200, 180, 120, 160]
}
df = pd.DataFrame(data)
# 创建数据透视表,按产品和类别汇总销售额
pivot_table = pd.pivot_table(df, values='Sales', index='Product', columns='Category', aggfunc='sum', fill_value=0)
print(pivot_table)
Category X Y
Product
A 220 200
B 150 340
(三)数据管道操作
数据管道是一种将多个数据处理步骤组合在一起的技术,Pandas 支持使用 apply
函数实现数据管道操作。
import pandas as pd
# 创建示例数据
data = {
'Text': ['apple', 'banana', 'orange', 'grape', 'pineapple']
}
df = pd.DataFrame(data)
# 定义数据处理管道函数
def text_processing(text):
# 转换为小写
text = text.lower()
# 替换特定字符
text = text.replace('a', 'X')
# 返回处理后的文本
return text
# 应用数据处理管道
df['Processed Text'] = df['Text'].apply(text_processing)
print(df)
Text Processed Text
0 apple Xpple
1 banana bXnXnX
2 orange orgXnge
3 grape grXpe
4 pineapple pXnXpXle
九、Pandas 的性能优化
在处理大规模数据时,Pandas 的性能可能会受到挑战。以下是一些优化 Pandas 性能的技巧:
-
使用合适的数据类型 :选择合适的数据类型可以减少内存占用,提高计算速度。例如,将整数列转换为更小的数据类型:
import pandas as pd
# 创建 DataFrame
df = pd.DataFrame({
'A': np.random.randint(0, 100, size=1000000)
})
# 转换列 A 的数据类型为更小的整数类型
df['A'] = df['A'].astype(np.int8)
-
避免使用 apply 函数 :
apply
函数在大多数情况下比矢量化操作慢得多。尽量使用 Pandas 的内置矢量化函数:
import pandas as pd
# 创建 DataFrame
df = pd.DataFrame({
'A': np.random.randn(1000000)
})
# 使用矢量化操作计算平方(推荐)
df['A_squared'] = df['A'] ** 2
# 使用 apply 函数计算平方(不推荐)
# df['A_squared'] = df['A'].apply(lambda x: x ** 2)
-
使用 chunksize 读取大文件 :当处理无法一次性加载到内存的大文件时,可以使用
chunksize
参数分块读取:
import pandas as pd
# 分块读取 CSV 文件
chunk_size = 10000
for chunk in pd.read_csv('large_file.csv', chunksize=chunk_size):
# 对每个数据块进行处理
process(chunk)
十、Pandas 的局限性与注意事项
尽管 Pandas 功能强大,但它也有一些局限性和需要注意的地方:
-
处理大规模数据的性能瓶颈 :对于非常大的数据集(如数十亿条记录),Pandas 可能会遇到性能瓶颈。在这种情况下,可以考虑使用分布式计算框架(如 Dask、Spark)或数据库解决方案。
-
复杂的文本处理能力有限 :对于复杂的文本处理任务,Pandas 的功能可能不如专门的文本处理库(如 NLTK、spaCy)强大。在这种情况下,可以结合使用 Pandas 和其他文本处理库。
-
实时数据处理的适用性有限 :Pandas 主要设计用于批处理数据,对于实时数据处理任务可能不太适用。实时数据处理通常需要使用流处理框架(如 Apache Kafka、Apache Flink)