Pandas:数据处理与分析
目录
一、Pandas 简介
二、Pandas 的安装与导入
三、Pandas 的核心数据结构
(一)Series
(二)DataFrame
四、Pandas 数据读取与写入
(一)读取数据
(二)写入数据
五、数据清洗与预处理
(一)处理缺失值
(二)数据去重
(三)数据转换
(四)数据合并与连接
六、数据探索与分析
(一)数据概览
(二)数据分组与聚合
(三)数据筛选与排序
七、Pandas 的实际应用案例
(一)金融数据分析
(二)销售数据分析
八、Pandas 的高级特性
(一)时间序列分析
(二)高级数据透视表
(三)数据管道操作
九、Pandas 的性能优化
十、Pandas 的局限性与注意事项
一、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 object1 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 pltfig, 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 pltmonthly_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)