一、Pandas简介
1.1 什么是Pandas
Pandas(Python Data Analysis Library)是基于NumPy开发的Python数据分析库,专门用于处理结构化数据(如表格数据、CSV文件、Excel文件等),提供了直观、高效的数据读取、清洗、筛选、分组、聚合等功能,是数据分析、数据挖掘的核心工具。
Pandas与NumPy的关系:
Pandas基于NumPy实现,底层使用ndarray存储数据,继承了NumPy的高效运算能力;
NumPy专注于多维数组运算,而Pandas专注于结构化数据处理,提供了更贴近实际业务的API;
两者协同使用,可高效完成从数据读取到分析的全流程。
核心数据结构:Series(一维结构化数据)、DataFrame(二维结构化数据,类似Excel表格)。
1.2 安装Pandas
使用pip命令安装,建议同时安装openpyxl(用于读取Excel文件):
1 2 3 4 5
| pip install pandas openpyxl
pip install pandas==1.5.3 openpyxl==3.1.2
|
验证安装是否成功:
1 2
| import pandas as pd print(pd.__version__)
|
二、Pandas核心数据结构:Series
2.1 什么是Series
Series是Pandas中用于存储一维结构化数据的核心结构,类似“带标签的数组”——由两部分组成:
与NumPy ndarray的区别:Series有明确的索引,可通过标签索引数据,更适合处理带标识的一维数据(如某一列数据)。
2.2 创建Series
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
| import pandas as pd import numpy as np
s1 = pd.Series([10, 20, 30, 40, 50]) print("默认索引的Series:") print(s1) print("Series的值:", s1.values) print("Series的索引:", s1.index)
s2 = pd.Series([100, 200, 300], index=["语文", "数学", "英语"]) print("\n自定义索引的Series:") print(s2) print("索引为'数学'的值:", s2["数学"])
dict_data = {"北京": 1100, "上海": 900, "广州": 700, "深圳": 800} s3 = pd.Series(dict_data) print("\n从字典创建的Series:") print(s3)
arr = np.array([1.1, 2.2, 3.3, 4.4]) s4 = pd.Series(arr, index=["a", "b", "c", "d"]) print("\n从NumPy数组创建的Series:") print(s4)
|
2.3 Series的索引与切片
Series支持两种索引方式:标签索引(label-based)和位置索引(position-based),切片语法与NumPy类似,但更灵活。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| import pandas as pd
s = pd.Series([10, 20, 30, 40, 50], index=["a", "b", "c", "d", "e"]) print("原始Series:") print(s)
print("\n单个标签索引('c'):", s["c"]) print("多个标签索引(['a','c','e']):", s[["a", "c", "e"]])
print("\n位置索引(下标2):", s.iloc[2]) print("位置切片(0:3):", s.iloc[0:3])
print("\n筛选大于30的元素:", s[s > 30]) print("筛选索引包含'a'或'e'的元素:", s[s.index.isin(["a", "e"])])
|
2.4 Series的常用操作与函数
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
| import pandas as pd import numpy as np
s = pd.Series([10, 20, np.nan, 40, 50, np.nan]) print("原始Series(含缺失值):") print(s)
print("\nSeries的长度:", len(s)) print("Series的描述性统计:") print(s.describe())
print("\n缺失值判断(True表示缺失):", s.isnull()) print("非缺失值判断:", s.notnull()) print("删除缺失值(dropna):", s.dropna()) print("填充缺失值(fillna):", s.fillna(s.mean()))
print("\nSeries + 5:", s + 5) print("Series * 2:", s * 2) print("Series的均值:", s.mean()) print("Series的总和:", s.sum())
s.index = ["x", "y", "z", "m", "n", "p"] print("\n重新设置索引后的Series:") print(s) s_reset = s.reset_index() print("\n索引转列后的结果:") print(s_reset)
|
三、Pandas核心数据结构:DataFrame
3.1 什么是DataFrame
DataFrame是Pandas中用于存储二维结构化数据的核心结构,类似Excel表格、SQL数据表,由行索引(index)和列索引(columns)组成,每个列可以是不同的数据类型(如int、float、str)。
核心特点:
3.2 创建DataFrame
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
| import pandas as pd import numpy as np
dict_data = { "姓名": ["张三", "李四", "王五", "赵六"], "年龄": [20, 21, 19, 22], "性别": ["男", "女", "男", "女"], "成绩": [85, 92, 78, 90] } df1 = pd.DataFrame(dict_data) print("从字典创建的DataFrame:") print(df1) print("DataFrame的行索引:", df1.index) print("DataFrame的列索引:", df1.columns)
df2 = pd.DataFrame(dict_data, index=["学生1", "学生2", "学生3", "学生4"]) print("\n自定义行索引的DataFrame:") print(df2)
arr = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]]) df3 = pd.DataFrame(arr, columns=["A", "B", "C"], index=["X", "Y", "Z"]) print("\n从NumPy数组创建的DataFrame:") print(df3)
|
3.3 DataFrame的索引与切片
DataFrame支持行、列的单独索引和组合索引,核心方法:
[]:默认对列进行操作(筛选列);
loc:标签索引(行标签+列标签);
iloc:位置索引(行下标+列下标);
布尔索引:按条件筛选行。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34
| import pandas as pd
data = { "姓名": ["张三", "李四", "王五", "赵六"], "年龄": [20, 21, 19, 22], "性别": ["男", "女", "男", "女"], "成绩": [85, 92, 78, 90] } df = pd.DataFrame(data, index=["学生1", "学生2", "学生3", "学生4"]) print("原始DataFrame:") print(df)
print("\n筛选单个列('姓名'):") print(df["姓名"]) print("\n筛选多个列(['姓名','成绩']):") print(df[["姓名", "成绩"]])
print("\nloc筛选(行:'学生2',列:'成绩'):", df.loc["学生2", "成绩"]) print("\nloc筛选(行:['学生1','学生3'],列:['姓名','年龄']):") print(df.loc[["学生1", "学生3"], ["姓名", "年龄"]])
print("\niloc筛选(行下标1,列下标3):", df.iloc[1, 3]) print("\niloc筛选(行下标0:2,列下标1:3):") print(df.iloc[0:2, 1:3])
print("\n筛选成绩大于85的行:") print(df[df["成绩"] > 85]) print("\n筛选性别为'男'且年龄小于21的行:") print(df[(df["性别"] == "男") & (df["年龄"] < 21)])
|
3.4 DataFrame的常用操作
3.4.1 行、列的增删改
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38
| import pandas as pd
data = { "姓名": ["张三", "李四", "王五"], "年龄": [20, 21, 19], "成绩": [85, 92, 78] } df = pd.DataFrame(data) print("原始DataFrame:") print(df)
df["班级"] = ["一班", "二班", "一班"] df["排名"] = [3, 1, 4] print("\n新增列后:") print(df)
df["成绩"] = df["成绩"] + 5 df.rename(columns={"班级": "所在班级"}, inplace=True) print("\n修改列后:") print(df)
df.drop(columns=["排名"], inplace=True) print("\n删除列后:") print(df)
new_row = pd.DataFrame({"姓名": ["赵六"], "年龄": [22], "成绩": [90], "所在班级": ["二班"]}) df = pd.concat([df, new_row], ignore_index=True) print("\n新增行后:") print(df)
df.drop(index=[2], inplace=True) print("\n删除行后:") print(df)
|
3.4.2 缺失值与重复值处理
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
| import pandas as pd import numpy as np
data = { "姓名": ["张三", "李四", "张三", "赵六", np.nan], "年龄": [20, np.nan, 20, 22, 19], "成绩": [85, 92, 85, np.nan, 78] } df = pd.DataFrame(data) print("原始DataFrame(含缺失值、重复值):") print(df)
print("\n缺失值统计(每列缺失值个数):") print(df.isnull().sum()) df1 = df.dropna() print("\n删除缺失值后:") print(df1) df2 = df.fillna({"年龄": df["年龄"].mean(), "成绩": df["成绩"].median()}) print("\n填充缺失值后:") print(df2)
print("\n重复值判断:") print(df.duplicated()) df3 = df.drop_duplicates() print("\n删除重复值后:") print(df3) df4 = df.drop_duplicates(subset=["姓名"], keep="last") print("\n按姓名去重(保留最后一行)后:") print(df4)
|
3.4.3 描述性统计与排序
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
| import pandas as pd
data = { "姓名": ["张三", "李四", "王五", "赵六"], "年龄": [20, 21, 19, 22], "成绩": [85, 92, 78, 90] } df = pd.DataFrame(data) print("原始DataFrame:") print(df)
print("\n数值列的描述性统计:") print(df.describe()) print("每列的均值:", df.mean(numeric_only=True)) print("每列的最大值:", df.max(numeric_only=True)) print("成绩列的中位数:", df["成绩"].median())
df_sorted1 = df.sort_values(by="成绩", ascending=False) print("\n按成绩降序排序:") print(df_sorted1) df_sorted2 = df.sort_values(by=["年龄", "成绩"], ascending=[True, False]) print("\n按年龄升序、成绩降序排序:") print(df_sorted2) df_sorted3 = df.sort_index() print("\n按索引排序:") print(df_sorted3)
|
四、Pandas数据读取与保存
实战中,数据分析的第一步是读取外部数据(如CSV、Excel、TXT),处理完成后需保存结果,Pandas提供了简洁的API实现。
4.1 读取常见数据格式
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| import pandas as pd
df_csv = pd.read_csv("data.csv")
df_csv2 = pd.read_csv("data.csv", sep=",", header=0, index_col="姓名")
df_excel = pd.read_excel("data.xlsx", sheet_name="Sheet1")
df_excel2 = pd.read_excel("data.xlsx", sheet_name=0, usecols=["姓名", "成绩"])
df_txt = pd.read_table("data.txt", sep="\t")
print("CSV文件数据:") print(df_csv.head()) print("\nExcel文件数据:") print(df_excel.tail(3))
|
4.2 保存数据到外部文件
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| import pandas as pd
data = { "姓名": ["张三", "李四", "王五", "赵六"], "年龄": [20, 21, 19, 22], "成绩": [85, 92, 78, 90] } df = pd.DataFrame(data)
df.to_csv("result.csv", index=False)
df.to_csv("result2.csv", sep=",", header=True, encoding="utf-8")
df.to_excel("result.xlsx", sheet_name="结果", index=False)
df.to_csv("result.txt", sep="\t", index=False)
print("数据保存完成!")
|
五、Pandas分组与聚合(核心实战)
分组(groupby)与聚合是数据分析的核心操作,用于按指定条件对数据分组,然后对每组进行统计(如求和、均值、计数),类似SQL的GROUP BY。
5.1 基本分组操作
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39
| import pandas as pd
data = { "班级": ["一班", "一班", "二班", "二班", "一班", "二班"], "姓名": ["张三", "李四", "王五", "赵六", "孙七", "周八"], "性别": ["男", "女", "男", "女", "男", "女"], "成绩": [85, 92, 78, 90, 88, 82] } df = pd.DataFrame(data) print("原始数据:") print(df)
group_by_class = df.groupby("班级")
print("\n按班级分组后的各组数据:") for name, group in group_by_class: print(f"班级:{name}") print(group) print("-" * 20)
group_by_class_gender = df.groupby(["班级", "性别"]) print("\n按班级+性别分组的结果:") print(group_by_class_gender.size())
print("\n按班级分组,计算成绩的均值和总和:") print(group_by_class["成绩"].agg(["mean", "sum"])) print("\n按班级+性别分组,计算成绩的最大值和最小值:") print(group_by_class_gender["成绩"].agg(["max", "min"]))
def range_func(x): return x.max() - x.min()
print("\n按班级分组,计算成绩范围:") print(group_by_class["成绩"].agg(range_func))
|
5.2 分组后的过滤(filter)
filter方法用于按分组后的条件,筛选出符合要求的组的所有数据。
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| import pandas as pd
data = { "班级": ["一班", "一班", "二班", "二班", "一班", "二班"], "姓名": ["张三", "李四", "王五", "赵六", "孙七", "周八"], "成绩": [85, 92, 78, 90, 88, 82] } df = pd.DataFrame(data)
group_by_class = df.groupby("班级") filtered_df = group_by_class.filter(lambda x: x["成绩"].mean() > 85) print("班级平均成绩大于85分的学生:") print(filtered_df)
|
六、Pandas实战小案例
案例:分析学生成绩数据,完成数据读取、清洗、筛选、分组统计全流程。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57
| import pandas as pd import numpy as np
df = pd.read_excel("data.xlsx", sheet_name="Sheet1") print("原始数据:") print(df.head())
print("\n数据清洗前:") print(f"缺失值统计:\n{df.isnull().sum()}") print(f"重复值数量:{df.duplicated().sum()}")
df["年龄"] = df["年龄"].fillna(df["年龄"].mean()) df["成绩"] = df["成绩"].fillna(df["成绩"].median())
df = df.drop_duplicates() print("\n数据清洗后:") print(f"缺失值统计:\n{df.isnull().sum()}") print(f"重复值数量:{df.duplicated().sum()}")
filtered_df = df[(df["成绩"] > 80) & (df["年龄"] < 22)] print("\n成绩大于80分且年龄小于22岁的学生:") print(filtered_df)
group_stats = df.groupby("班级")["成绩"].agg([ "count", "mean", "max", "min", "std" ]).round(2) group_stats.columns = ["人数", "平均分", "最高分", "最低分", "标准差"] print("\n按班级分组统计成绩:") print(group_stats)
def grade_level(score): if score >= 90: return "优秀" elif score >= 80: return "良好" elif score >= 60: return "及格" else: return "不及格"
df["成绩等级"] = df["成绩"].apply(grade_level) print("\n新增成绩等级列后:") print(df[["姓名", "班级", "成绩", "成绩等级"]].head())
df.to_excel("processed_data.xlsx", sheet_name="处理后数据", index=False) print("\n处理后的数据已保存到processed_data.xlsx!")
|
七、常见问题与注意事项
数据类型问题:读取数据时,Pandas会自动推断数据类型,若需指定类型(如将“年龄”设为int),可使用dtype参数(如pd.read_csv("data.csv", dtype={"年龄": int}))。
缺失值处理:dropna()会删除含缺失值的行/列,fillna()可填充缺失值,需根据业务场景选择(如数值型用均值/中位数,分类型用众数)。
inplace参数:大部分修改操作(如drop、rename、fillna)都有inplace参数,设为True表示修改原DataFrame,False表示返回新的DataFrame(默认False)。
分组聚合时的列选择:groupby后若只对某一列聚合,需指定列名(如group_by_class["成绩"].mean()),否则会对所有数值列聚合。
索引问题:重置索引用reset_index(),设置索引用set_index(),避免索引混乱导致的数据筛选错误。
中文编码问题:读取/保存含中文的文件时,需指定encoding="utf-8",避免中文乱码。
八、总结
Pandas是Python数据分析的核心工具,重点掌握以下内容:
核心数据结构:Series(一维)、DataFrame(二维)的创建与基本操作;
索引与切片:loc(标签)、iloc(位置)、布尔索引的灵活使用;
数据清洗:缺失值、重复值的处理方法;
数据读取与保存:CSV、Excel文件的读写操作;
分组与聚合:groupby的使用,以及常见聚合函数的应用;
实战能力:结合案例,完成从数据读取到分析、保存的全流程。
Pandas的功能远不止于此,后续可深入学习合并(merge)、拼接(concat)、透视表(pivot_table)等高级功能,结合Matplotlib可实现数据可视化,为数据分析提供更直观的呈现。