Python入门第12课:数据处理神器,Pandas基础操作完全指南
作者: 蛋皮
标签: Python, Pandas, 数据分析, DataFrame, Series, 数据处理, 数据科学
欢迎回到Python入门系列!在上一课中,我们学会了如何使用requests库让Python程序与互联网对话,获取丰富的在线数据。然而,获取到的数据往往是原始的、杂乱的,如何高效地清洗、整理、分析这些数据,从中提炼出有价值的信息?这就是我们今天要学习的主角——Pandas 的用武之地。
Pandas是Python中最强大、最流行的数据分析和处理库。它提供了两种核心数据结构:Series 和 DataFrame,让处理表格数据(如Excel、CSV)变得像操作电子表格一样直观,同时又具备编程的灵活性和可重复性。无论你是数据分析新手,还是希望自动化报表生成,Pandas都是你必须掌握的“瑞士军刀”。
为什么选择 Pandas?
在Pandas出现之前,处理结构化数据主要依赖于Python内置的列表和字典,或者NumPy数组,但这对于复杂的表格操作来说非常繁琐。Pandas的诞生极大地简化了这一过程:
- 直观的DataFrame: 就像一个超级强大的Excel表格,支持行、列标签索引。
- 强大的数据清洗能力: 轻松处理缺失值、重复数据、数据类型转换。
- 高效的计算与聚合: 内置丰富的统计函数,支持分组、透视表等复杂操作。
- 无缝的I/O支持: 轻松读写CSV、Excel、JSON、SQL数据库等多种格式。
- 与生态完美集成: 与
Matplotlib(绘图)、Scikit-learn(机器学习)等库无缝协作。
一句话:Pandas让你用Python高效地完成Excel能做,甚至Excel做不了的数据处理任务。
准备工作:安装与导入
确保已安装Pandas库。打开命令行执行:
pip install pandas
安装完成后,在Python脚本中导入:
import pandas as pd # 惯例:导入pandas并简写为pd
核心数据结构:Series 与 DataFrame
1. Series:一维带标签的数组
Series 可以看作是一个一维数组,但它有一个索引 (Index),用于标识每个元素。
import pandas as pd
# 创建一个Series (例如,表示几个学生的分数)
scores = pd.Series([85, 92, 78, 96, 88], index=['Alice', 'Bob', 'Charlie', 'Diana', 'Eve'], name='Math Scores')
print(scores)
print(f"数据类型: {scores.dtype}")
print(f"索引: {scores.index}")
print(f"值: {scores.values}")
输出:
Alice 85
Bob 92
Charlie 78
Diana 96
Eve 88
Name: Math Scores, dtype: int64
数据类型: int64
索引: Index(['Alice', 'Bob', 'Charlie', 'Diana', 'Eve'], dtype='object')
值: [85 92 78 96 88]
关键点:
index: 每个元素的标签,可以是字符串、数字等,不一定是0, 1, 2…name: Series的名字。dtype: 数据类型。
2. DataFrame:二维带标签的表格
DataFrame 是Pandas的核心,可以看作是一个电子表格或SQL表,由多列Series组成,每行和每列都有标签。
创建DataFrame
# 方法1: 从字典创建 (最常见)
data = {
'Name': ['Alice', 'Bob', 'Charlie', 'Diana', 'Eve'],
'Age': [23, 25, 22, 24, 26],
'City': ['Beijing', 'Shanghai', 'Guangzhou', 'Shenzhen', 'Hangzhou'],
'Score': [85, 92, 78, 96, 88]
}
df = pd.DataFrame(data)
print(df)
输出:
Name Age City Score
0 Alice 23 Beijing 85
1 Bob 25 Shanghai 92
2 Charlie 22 Guangzhou 78
3 Diana 24 Shenzhen 96
4 Eve 26 Hangzhou 88
# 方法2: 从列表的列表创建 (较少用)
data_list = [
['Alice', 23, 'Beijing', 85],
['Bob', 25, 'Shanghai', 92],
['Charlie', 22, 'Guangzhou', 78],
['Diana', 24, 'Shenzhen', 96],
['Eve', 26, 'Hangzhou', 88]
]
df2 = pd.DataFrame(data_list, columns=['Name', 'Age', 'City', 'Score'])
# 方法3: 从其他DataFrame切片创建
df_subset = df[['Name', 'Score']] # 只取Name和Score两列
DataFrame基础操作
1. 查看数据
# 显示前几行 (默认5行)
print(df.head())
# 显示后几行 (默认5行)
print(df.tail(3))
# 查看数据的形状 (行数, 列数)
print(f"数据形状: {df.shape}") # (5, 4)
# 查看列名
print(f"列名: {df.columns.tolist()}")
# 查看数据类型
print(df.dtypes)
# 简要统计信息 (仅对数值列)
print(df.describe())
# 查看数据整体信息 (非空值数量、数据类型等)
df.info()
2. 索引与选择数据
这是Pandas最核心的操作之一。
# 选择单列 (返回Series)
names = df['Name']
print(type(names)) # <class 'pandas.core.series.Series'>
print(names)
# 选择多列 (返回DataFrame)
subset = df[['Name', 'Score']]
print(type(subset)) # <class 'pandas.core.frame.DataFrame'>
print(subset)
# 使用 .loc[]: 基于标签 (label) 选择
# 选择第0行 (标签为0) 的 'Name' 和 'Score' 列
print(df.loc[0, ['Name', 'Score']])
# 选择标签为 'Bob' 的行 (需要设置Name为索引先)
df_indexed = df.set_index('Name')
print(df_indexed.loc['Bob', 'Score'])
# 选择多行多列
print(df.loc[1:3, 'Age':'City']) # 注意:loc是包含结束索引的!
# 使用 .iloc[]: 基于位置 (integer location) 选择
# 选择第1行 (位置1) 的第2列 (位置2, 即City)
print(df.iloc[1, 2])
# 选择第1到第3行,第1到第3列 (位置)
print(df.iloc[1:4, 1:4]) # 注意:iloc是不包含结束位置的!
3. 增加、修改、删除数据
# 增加新列
df['Grade'] = ['B', 'A', 'C', 'A', 'B'] # 直接赋值
df['Pass'] = df['Score'] >= 80 # 基于现有列计算
print(df)
# 修改现有列的值
df.loc[0, 'Score'] = 87 # 将Alice的分数改为87
df['Age'] = df['Age'] + 1 # 所有人年龄加1岁
# 删除列
df_dropped = df.drop('Pass', axis=1) # axis=1 表示列,不修改原df
# df.drop('Pass', axis=1, inplace=True) # inplace=True 直接在原df上修改
# 删除行
df_dropped_row = df.drop(0, axis=0) # 删除索引为0的行
4. 数据清洗:处理缺失值
真实数据常有缺失(用NaN表示)。
import numpy as np
# 创建一个包含缺失值的DataFrame
data_with_nan = {
'Name': ['Alice', 'Bob', 'Charlie', 'Diana'],
'Age': [23, np.nan, 22, 24],
'Score': [85, 92, np.nan, 96]
}
df_nan = pd.DataFrame(data_with_nan)
# 检查缺失值
print(df_nan.isnull())
print(f"缺失值总数: {df_nan.isnull().sum().sum()}")
# 处理缺失值
# 方法1: 删除包含缺失值的行
df_cleaned = df_nan.dropna() # 删除任何有NaN的行
# 方法2: 填充缺失值
df_filled = df_nan.fillna(0) # 用0填充
df_filled_mean = df_nan.copy()
df_filled_mean['Age'].fillna(df_filled_mean['Age'].mean(), inplace=True) # 用平均值填充Age
df_filled_mean['Score'].fillna(df_filled_mean['Score'].median(), inplace=True) # 用中位数填充Score
print(df_filled_mean)
5. 数据类型转换
# 查看数据类型
print(df.dtypes)
# 转换数据类型
df['Age'] = df['Age'].astype(int) # 转换为整数
df['Pass'] = df['Pass'].astype(bool) # 转换为布尔值
# 如果有日期字符串,可以转换为datetime
# df['Date'] = pd.to_datetime(df['Date'])
数据操作:筛选、排序与分组
1. 筛选 (Filtering)
# 筛选分数大于90的学生
high_scorers = df[df['Score'] > 90]
print(high_scorers)
# 筛选来自北京或上海的学生
beijing_shanghai = df[df['City'].isin(['Beijing', 'Shanghai'])]
# 复合条件 (使用 & 和 |,注意括号)
good_young = df[(df['Score'] > 85) & (df['Age'] < 25)]
print(good_young)
2. 排序 (Sorting)
# 按分数降序排序
df_sorted = df.sort_values('Score', ascending=False)
print(df_sorted)
# 按多个列排序 (先按City升序,再按Score降序)
df_sorted_multi = df.sort_values(['City', 'Score'], ascending=[True, False])
3. 分组聚合 (GroupBy)
这是Pandas最强大的功能之一,类似于Excel的“数据透视表”或SQL的GROUP BY。
# 按城市分组,计算每个城市的平均分数和最大年龄
grouped = df.groupby('City').agg({
'Score': ['mean', 'max'], # 对Score列计算平均值和最大值
'Age': 'max' # 对Age列计算最大值
})
print(grouped)
# 更简洁的写法
avg_score_by_city = df.groupby('City')['Score'].mean()
print(avg_score_by_city)
# 按城市和等级分组
grouped_multi = df.groupby(['City', 'Grade'])['Score'].mean()
print(grouped_multi)
数据输入/输出 (I/O)
Pandas可以轻松读写多种文件格式。
1. 读取数据
# 读取CSV文件
# df_csv = pd.read_csv('data.csv')
# 读取Excel文件 (需要 openpyxl 或 xlrd)
# df_excel = pd.read_excel('data.xlsx', sheet_name='Sheet1')
# 读取JSON文件
# df_json = pd.read_json('data.json')
# 读取剪贴板 (复制表格内容后)
# df_clipboard = pd.read_clipboard()
# 读取在线数据 (结合requests)
# import requests
# url = "https://example.com/data.csv"
# response = requests.get(url)
# df_online = pd.read_csv(io.StringIO(response.text))
2. 写入数据
# 写入CSV文件 (不保存索引)
df.to_csv('output.csv', index=False)
# 写入Excel文件
# df.to_excel('output.xlsx', sheet_name='Results', index=False)
# 写入JSON文件
# df.to_json('output.json', orient='records', indent=2)
一个完整的例子:学生成绩分析
import pandas as pd
import numpy as np
# 1. 创建模拟数据
np.random.seed(0) # 保证结果可重现
names = ['Alice', 'Bob', 'Charlie', 'Diana', 'Eve', 'Frank', 'Grace', 'Henry']
data = {
'Student': names,
'Math': np.random.randint(60, 100, size=len(names)),
'English': np.random.randint(65, 98, size=len(names)),
'Science': np.random.randint(55, 95, size=len(names))
}
df_grades = pd.DataFrame(data)
# 2. 数据清洗与处理
# 假设Diana的Science成绩缺失
df_grades.loc[df_grades['Student'] == 'Diana', 'Science'] = np.nan
# 计算总分和平均分
df_grades['Total'] = df_grades[['Math', 'English', 'Science']].sum(axis=1, skipna=True)
df_grades['Average'] = df_grades[['Math', 'English', 'Science']].mean(axis=1)
# 3. 数据分析
print("=== 学生成绩表 ===")
print(df_grades)
print("\n=== 各科平均分 ===")
print(df_grades[['Math', 'English', 'Science']].mean())
print("\n=== 总分前3名 ===")
top_students = df_grades.sort_values('Total', ascending=False).head(3)
print(top_students[['Student', 'Total']])
print("\n=== 每科最高分 ===")
max_scores = df_grades[['Math', 'English', 'Science']].max()
print(max_scores)
# 4. 保存结果
df_grades.to_csv('student_grades_analysis.csv', index=False)
print("\n分析结果已保存到 'student_grades_analysis.csv'")
最佳实践与总结
- 链式操作 (Method Chaining): Pandas支持链式调用,让代码更紧凑。
result = (df[df['Score'] > 80] .sort_values('Score', ascending=False) .head(10) .reset_index(drop=True)) - 避免循环: 尽量使用Pandas内置的向量化操作(如
df['col'] > value),而不是对行进行for循环,效率更高。 - 理解
inplace:inplace=True会修改原对象,inplace=False(默认) 返回新对象。谨慎使用inplace,以免意外修改原始数据。 - 处理缺失值: 明确你的数据中
NaN的含义,并选择合适的处理策略(删除、填充、插值)。 - 内存管理: 大型DataFrame会占用较多内存。考虑使用合适的数据类型(如
categoryfor strings with few unique values)。 - 探索性数据分析 (EDA):
head(),info(),describe()是你开始分析数据的好朋友。
总结
通过本课的学习,你已经掌握了Pandas的基础操作。你学会了:
- 创建和理解 Series 和 DataFrame。
- 查看、选择、修改 数据。
- 清洗 数据(处理缺失值、类型转换)。
- 筛选、排序、分组聚合 数据。
- 读写 CSV、Excel等文件。
Pandas是数据科学的基石。它将繁琐的数据处理工作变得简单高效。接下来,你可以将requests获取的网络数据,用Pandas进行清洗和分析,再用matplotlib绘制成图表,完成一个完整的数据处理流程。
练习建议:
- 创建一个包含你朋友信息的DataFrame(姓名、年龄、城市、爱好)。
- 从网上下载一个CSV文件(如Kaggle上的公开数据集),用Pandas读取并进行基本分析。
- 练习使用
groupby进行各种分组统计。 - 尝试将上一课获取的天气数据用Pandas组织起来。
724

被折叠的 条评论
为什么被折叠?



