Pandas数据处理从入门到精通:数据清洗、分析与可视化实战
在日常数据处理工作中我们经常面临Excel表格数据清洗、SQL查询结果分析、时间序列数据处理等任务。传统的手工操作不仅效率低下而且容易出错。Pandas作为Python生态中最强大的数据处理库能够帮助我们高效完成这些工作。本文将带你从零开始系统学习Pandas涵盖安装配置、核心数据结构、数据操作、数据分析等完整知识体系每个知识点都配有可运行的代码示例。1. Pandas基础概念与环境搭建1.1 什么是PandasPandas是基于Python构建的开源数据分析和处理库专门设计用于处理表格型数据。它提供了DataFrame和Series两种核心数据结构使得数据操作变得直观高效。Pandas的名称源自panel data面板数据体现了其处理多维度时间序列数据的能力。在实际应用中Pandas可以处理各种数据格式包括CSV、Excel、SQL数据库、JSON等。无论是数据清洗、转换、聚合还是可视化Pandas都能提供简洁的API接口。根据PyPI的下载统计Pandas已成为数据科学领域最受欢迎的Python库之一日均下载量超过百万次。1.2 环境安装与配置安装Pandas前需要确保已安装Python环境推荐Python 3.7及以上版本。可以通过pip或conda进行安装# 使用pip安装 pip install pandas # 使用conda安装 conda install pandas # 安装完整的数据科学套件推荐 pip install pandas numpy matplotlib jupyter验证安装是否成功import pandas as pd print(fPandas版本: {pd.__version__})对于需要处理大型数据集的用户可以考虑安装GPU加速版本# 安装RAPIDS cuDF需要NVIDIA GPU # 注意仅适用于Linux系统且需要CUDA环境 pip install cudf-cu111.3 Jupyter Notebook环境配置Jupyter Notebook是学习Pandas的最佳工具提供交互式编程体验# 安装Jupyter pip install jupyter # 启动Jupyter jupyter notebook在Notebook中创建第一个Pandas示例import pandas as pd import numpy as np # 创建简单的DataFrame data {姓名: [张三, 李四, 王五], 年龄: [25, 30, 35], 城市: [北京, 上海, 广州]} df pd.DataFrame(data) print(df)运行结果姓名 年龄 城市 0 张三 25 北京 1 李四 30 上海 2 王五 35 广州2. 核心数据结构Series和DataFrame2.1 Series数据结构Series是Pandas中最基本的一维数据结构类似于带标签的数组# 创建Series的多种方式 # 从列表创建 s1 pd.Series([1, 3, 5, np.nan, 6, 8]) print(从列表创建:) print(s1) # 从字典创建字典的key成为索引 s2 pd.Series({a: 1, b: 2, c: 3}) print(\n从字典创建:) print(s2) # 指定索引和数据类型 s3 pd.Series([10, 20, 30], index[x, y, z], dtypefloat) print(\n指定索引和类型:) print(s3)Series的常用操作# Series基本操作 s pd.Series([1, 2, 3, 4, 5], index[a, b, c, d, e]) print(原始Series:) print(s) print(\n索引访问:) print(s[c]) # 通过标签访问 print(s[2]) # 通过位置访问 print(\n切片操作:) print(s[b:d]) # 标签切片包含两端 print(s[1:4]) # 位置切片左闭右开 print(\n基本统计:) print(f平均值: {s.mean()}) print(f总和: {s.sum()}) print(f最大值: {s.max()})2.2 DataFrame数据结构DataFrame是Pandas的核心是二维的表格型数据结构# 创建DataFrame的多种方式 # 从字典创建 data { 姓名: [张三, 李四, 王五, 赵六], 年龄: [28, 32, 25, 40], 工资: [5000, 8000, 6000, 12000], 部门: [技术部, 销售部, 技术部, 人事部] } df pd.DataFrame(data) print(从字典创建DataFrame:) print(df) # 从列表创建需要指定列名 data_list [[张三, 28, 5000], [李四, 32, 8000], [王五, 25, 6000]] df2 pd.DataFrame(data_list, columns[姓名, 年龄, 工资]) print(\n从列表创建DataFrame:) print(df2) # 从NumPy数组创建 import numpy as np arr np.random.randn(3, 4) df3 pd.DataFrame(arr, columns[A, B, C, D]) print(\n从NumPy数组创建:) print(df3)2.3 DataFrame的基本属性与方法# 创建示例DataFrame data { 员工ID: [101, 102, 103, 104, 105], 姓名: [张三, 李四, 王五, 赵六, 钱七], 年龄: [28, 35, 22, 40, 31], 部门: [技术部, 销售部, 技术部, 人事部, 销售部], 工资: [8000, 12000, 6000, 10000, 15000], 入职日期: pd.date_range(20220101, periods5) } df pd.DataFrame(data) df.set_index(员工ID, inplaceTrue) # 设置员工ID为索引 print(DataFrame基本信息:) print(f形状: {df.shape}) # 行列数 print(f维度: {df.ndim}) # 维度数 print(f列名: {df.columns.tolist()}) # 列名称 print(f索引: {df.index.tolist()}) # 索引值 print(\n数据类型:) print(df.dtypes) print(\n前3行数据:) print(df.head(3)) print(\n后2行数据:) print(df.tail(2)) print(\n描述性统计:) print(df.describe())3. 数据导入与导出3.1 读取CSV文件CSV是最常用的数据交换格式Pandas提供了强大的读取功能# 读取CSV文件的基本用法 # 假设有一个sales.csv文件内容如下 # date,product,sales,region # 2023-01-01,A,100,North # 2023-01-02,B,150,South # 2023-01-03,A,200,North df_csv pd.read_csv(sales.csv) print(读取CSV文件:) print(df_csv) # 带参数的读取 df_csv_advanced pd.read_csv( sales.csv, sep,, # 分隔符 header0, # 表头行号 index_coldate, # 索引列 parse_datesTrue, # 解析日期 encodingutf-8 # 编码格式 ) print(\n高级参数读取:) print(df_csv_advanced)3.2 读取Excel文件对于Excel文件Pandas需要依赖openpyxl或xlrd库# 安装依赖库 # pip install openpyxl xlrd # 读取Excel文件 df_excel pd.read_excel(data.xlsx, sheet_nameSheet1) print(读取Excel文件:) print(df_excel) # 读取多个sheet with pd.ExcelFile(data.xlsx) as xls: df_sheet1 pd.read_excel(xls, Sheet1) df_sheet2 pd.read_excel(xls, Sheet2) # 带参数的Excel读取 df_excel_advanced pd.read_excel( data.xlsx, sheet_name0, # 第一个sheet header0, # 第一行为表头 usecolsA:D, # 只读取A-D列 na_values[NA, NULL] # 将NA和NULL识别为缺失值 )3.3 从数据库读取数据Pandas可以方便地从SQL数据库读取数据import sqlite3 # 创建示例数据库 conn sqlite3.connect(example.db) cursor conn.cursor() # 创建表并插入数据 cursor.execute( CREATE TABLE IF NOT EXISTS employees ( id INTEGER PRIMARY KEY, name TEXT, department TEXT, salary INTEGER ) ) cursor.execute(INSERT INTO employees VALUES (1, 张三, 技术部, 8000)) cursor.execute(INSERT INTO employees VALUES (2, 李四, 销售部, 12000)) conn.commit() # 从数据库读取数据 df_sql pd.read_sql(SELECT * FROM employees, conn) print(从数据库读取:) print(df_sql) conn.close()3.4 数据导出将处理后的数据保存为各种格式# 创建示例数据 data { 产品: [A, B, C, D], 销量: [100, 150, 200, 120], 价格: [10.5, 20.3, 15.7, 25.0] } df pd.DataFrame(data) # 保存为CSV df.to_csv(output.csv, indexFalse, encodingutf-8-sig) # 保存为Excel df.to_excel(output.xlsx, sheet_name销售数据, indexFalse) # 保存为JSON df.to_json(output.json, orientrecords, force_asciiFalse) # 保存到数据库 import sqlite3 conn sqlite3.connect(output.db) df.to_sql(sales_data, conn, if_existsreplace, indexFalse) conn.close()4. 数据清洗与预处理4.1 处理缺失值真实数据中经常存在缺失值Pandas提供了多种处理方式# 创建包含缺失值的示例数据 data { 姓名: [张三, 李四, 王五, 赵六, None], 年龄: [25, 30, None, 35, 28], 工资: [5000, None, 6000, 7000, 5500], 部门: [技术部, 销售部, None, 技术部, 销售部] } df pd.DataFrame(data) print(原始数据包含缺失值:) print(df) # 检测缺失值 print(\n缺失值统计:) print(df.isnull().sum()) print(\n缺失值位置:) print(df.isnull()) # 处理缺失值 print(\n删除包含缺失值的行:) df_dropna df.dropna() print(df_dropna) print(\n填充缺失值:) df_fillna df.fillna({ 姓名: 未知, 年龄: df[年龄].mean(), 工资: df[工资].median(), 部门: 未分配 }) print(df_fillna) # 向前填充或向后填充 df_ffill df.ffill() # 用前一个有效值填充 df_bfill df.bfill() # 用后一个有效值填充4.2 数据类型转换正确的数据类型对于数据分析至关重要# 创建混合类型数据 data { 字符串数字: [1, 2, 3, 4], 数字字符串: [100, 200, 300, 400], 日期字符串: [2023-01-01, 2023-01-02, 2023-01-03, 2023-01-04], 布尔字符串: [True, False, True, False] } df pd.DataFrame(data) print(原始数据类型:) print(df.dtypes) # 数据类型转换 df[字符串数字] pd.to_numeric(df[字符串数字]) df[数字字符串] df[数字字符串].astype(str) df[日期字符串] pd.to_datetime(df[日期字符串]) df[布尔字符串] df[布尔字符串].map({True: True, False: False}) print(\n转换后数据类型:) print(df.dtypes) print(\n转换后数据:) print(df)4.3 数据去重与重复值处理# 创建包含重复值的数据 data { 姓名: [张三, 李四, 张三, 王五, 李四], 年龄: [25, 30, 25, 35, 30], 部门: [技术部, 销售部, 技术部, 人事部, 销售部] } df pd.DataFrame(data) print(原始数据包含重复:) print(df) # 检测重复行 print(\n重复行检测:) print(df.duplicated()) print(\n按姓名检测重复:) print(df.duplicated(subset[姓名])) # 删除重复行 print(\n删除完全重复的行:) df_dedup df.drop_duplicates() print(df_dedup) print(\n按姓名删除重复保留第一个:) df_dedup_name df.drop_duplicates(subset[姓名], keepfirst) print(df_dedup_name) print(\n按姓名删除重复保留最后一个:) df_dedup_last df.drop_duplicates(subset[姓名], keeplast) print(df_dedup_last)4.4 数据替换与映射# 创建示例数据 data { 等级: [A, B, C, A, B, D], 分数: [90, 80, 70, 95, 85, 60] } df pd.DataFrame(data) print(原始数据:) print(df) # 简单替换 df_replace df.replace(D, C) print(\n替换D为C:) print(df_replace) # 多值替换 df_replace_multi df.replace({A: 优秀, B: 良好, C: 及格, D: 不及格}) print(\n多值映射替换:) print(df_replace_multi) # 使用map进行列映射 grade_map {A: 4.0, B: 3.0, C: 2.0, D: 1.0} df[等级分数] df[等级].map(grade_map) print(\n使用map添加新列:) print(df) # 使用apply进行复杂转换 def grade_category(score): if score 90: return 优秀 elif score 80: return 良好 elif score 70: return 及格 else: return 不及格 df[分数等级] df[分数].apply(grade_category) print(\n使用apply进行复杂转换:) print(df)5. 数据筛选与索引5.1 基本索引操作# 创建示例数据 data { 姓名: [张三, 李四, 王五, 赵六, 钱七], 年龄: [25, 30, 35, 28, 32], 部门: [技术部, 销售部, 技术部, 人事部, 销售部], 工资: [8000, 12000, 15000, 9000, 11000] } df pd.DataFrame(data) df.set_index(姓名, inplaceTrue) print(原始数据:) print(df) # 基本的索引操作 print(\n选择单列:) print(df[年龄]) print(\n选择多列:) print(df[[年龄, 工资]]) print(\n使用loc按标签选择:) print(df.loc[[张三, 王五]]) # 选择特定行 print(df.loc[:, [年龄, 部门]]) # 选择特定列 print(\n使用iloc按位置选择:) print(df.iloc[0]) # 第一行 print(df.iloc[1:3]) # 第2-3行 print(df.iloc[:, 0:2]) # 前两列5.2 布尔索引条件筛选布尔索引是Pandas中最强大的数据筛选功能# 继续使用上面的df print(原始数据:) print(df) # 简单条件筛选 print(\n年龄大于30的员工:) print(df[df[年龄] 30]) print(\n技术部的员工:) print(df[df[部门] 技术部]) # 多条件组合 print(\n技术部且工资大于10000的员工:) print(df[(df[部门] 技术部) (df[工资] 10000)]) print(\n年龄小于30或大于35的员工:) print(df[(df[年龄] 30) | (df[年龄] 35)]) # 使用query方法 print(\n使用query方法筛选:) print(df.query(年龄 30 and 工资 10000)) # 字符串方法筛选 print(\n姓名包含三的员工:) print(df[df.index.str.contains(三)]) # isin方法筛选 print(\n部门为技术部或销售部的员工:) print(df[df[部门].isin([技术部, 销售部])])5.3 高级索引技巧# 重置索引以便演示 df_reset df.reset_index() print(重置索引后的数据:) print(df_reset) # 设置多重索引 df_multi df_reset.set_index([部门, 姓名]) print(\n多重索引数据:) print(df_multi) # 多重索引的查询 print(\n技术部的所有员工:) print(df_multi.loc[技术部]) print(\n特定部门和姓名:) print(df_multi.loc[(技术部, 王五)]) # 使用xs进行交叉选择 print(\n使用xs选择所有部门的张三:) print(df_multi.xs(张三, level姓名)) # 索引重置和排序 print(\n重置索引:) print(df_multi.reset_index()) print(\n按工资降序排序:) print(df.sort_values(工资, ascendingFalse)) print(\n按部门升序、工资降序排序:) print(df.sort_values([部门, 工资], ascending[True, False]))6. 数据聚合与分组操作6.1 基本分组操作GroupBy是Pandas最强大的功能之一用于数据聚合# 创建销售数据示例 data { 销售员: [张三, 李四, 王五, 张三, 李四, 王五, 张三, 李四], 产品类别: [电子, 电子, 电子, 服装, 服装, 服装, 家居, 家居], 销售额: [1000, 1200, 800, 500, 600, 400, 300, 450], 月份: [1月, 1月, 1月, 2月, 2月, 2月, 3月, 3月] } df pd.DataFrame(data) print(原始销售数据:) print(df) # 基本分组 grouped df.groupby(销售员) print(\n按销售员分组:) print(grouped.groups) # 显示分组情况 # 分组后的聚合操作 print(\n每个销售员的销售总额:) print(grouped[销售额].sum()) print(\n每个销售员的平均销售额:) print(grouped[销售额].mean()) print(\n每个销售员的销售统计:) print(grouped[销售额].describe())6.2 多列分组与复杂聚合# 多列分组 multi_grouped df.groupby([销售员, 产品类别]) print(按销售员和产品类别分组后的销售额总和:) print(multi_grouped[销售额].sum()) print(\n分组后的详细统计:) print(multi_grouped[销售额].agg([sum, mean, count, std])) # 自定义聚合函数 def sales_range(x): return x.max() - x.min() print(\n使用自定义聚合函数:) result multi_grouped[销售额].agg({ 总销售额: sum, 平均销售额: mean, 销售次数: count, 销售极差: sales_range }) print(result)6.3 分组后的数据转换# 创建包含日期的新示例 dates pd.date_range(20230101, periods6) data { 日期: dates, 城市: [北京, 上海, 广州, 北京, 上海, 广州], 销售额: [100, 150, 120, 130, 140, 110], 产品: [A, A, A, B, B, B] } df_dates pd.DataFrame(data) print(带日期的销售数据:) print(df_dates) # 分组后转换 df_dates[城市平均销售额] df_dates.groupby(城市)[销售额].transform(mean) df_dates[产品平均销售额] df_dates.groupby(产品)[销售额].transform(mean) print(\n添加分组平均值后的数据:) print(df_dates) # 使用apply进行复杂分组操作 def top_sales(group): return group.nlargest(1, 销售额) print(\n每个城市销售额最高的记录:) print(df_dates.groupby(城市).apply(top_sales))7. 数据合并与连接7.1 基本合并操作在实际项目中数据通常分布在多个表中需要合并分析# 创建多个相关表格 # 员工基本信息表 employees pd.DataFrame({ 员工ID: [1, 2, 3, 4], 姓名: [张三, 李四, 王五, 赵六], 部门ID: [101, 102, 101, 103] }) # 部门信息表 departments pd.DataFrame({ 部门ID: [101, 102, 103], 部门名称: [技术部, 销售部, 人事部], 部门经理: [经理A, 经理B, 经理C] }) # 工资信息表 salaries pd.DataFrame({ 员工ID: [1, 2, 3, 4, 5], # 注意有员工ID5不存在于员工表 工资: [8000, 12000, 15000, 9000, 10000], 发放日期: [2023-01-01, 2023-01-01, 2023-01-01, 2023-01-01, 2023-01-01] }) print(员工表:) print(employees) print(\n部门表:) print(departments) print(\n工资表:) print(salaries)7.2 多种合并方式# 内连接默认 inner_merge pd.merge(employees, departments, on部门ID) print(内连接结果只保留匹配的记录:) print(inner_merge) # 左连接保留左表所有记录 left_merge pd.merge(employees, departments, on部门ID, howleft) print(\n左连接结果:) print(left_merge) # 右连接保留右表所有记录 right_merge pd.merge(employees, salaries, on员工ID, howright) print(\n右连接结果:) print(right_merge) # 外连接保留所有记录 outer_merge pd.merge(employees, salaries, on员工ID, howouter) print(\n外连接结果:) print(outer_merge) # 多表连接 # 先连接员工和部门再连接工资 multi_merge pd.merge( pd.merge(employees, departments, on部门ID), salaries, on员工ID, howleft ) print(\n多表连接结果:) print(multi_merge)7.3 纵向合并Concatenation# 创建多个结构相同的表格 df1 pd.DataFrame({ 姓名: [张三, 李四], 销售额: [1000, 1500], 月份: [1月, 1月] }) df2 pd.DataFrame({ 姓名: [王五, 赵六], 销售额: [1200, 800], 月份: [2月, 2月] }) df3 pd.DataFrame({ 姓名: [钱七, 孙八], 销售额: [900, 1100], 月份: [3月, 3月] }) print(三个月的销售数据:) print(df1:, df1.shape) print(df2:, df2.shape) print(df3:, df3.shape) # 纵向合并 df_combined pd.concat([df1, df2, df3], ignore_indexTrue) print(\n合并后的数据:) print(df_combined) print(形状:, df_combined.shape)8. 时间序列数据处理8.1 时间索引创建与操作Pandas对时间序列数据有很好的支持# 创建时间序列数据 dates pd.date_range(2023-01-01, periods10, freqD) data { 日期: dates, 销售额: [100, 120, 110, 130, 125, 140, 135, 150, 145, 160], 产品: [A]*5 [B]*5 } df_time pd.DataFrame(data) df_time.set_index(日期, inplaceTrue) print(时间序列数据:) print(df_time) # 时间索引的特性 print(\n时间索引信息:) print(f索引类型: {type(df_time.index)}) print(f时间范围: {df_time.index.min()} 到 {df_time.index.max()}) print(f时间长度: {len(df_time.index)} 天) # 按时间筛选 print(\n2023年1月前5天的数据:) print(df_time[2023-01-01:2023-01-05]) print(\n1月份的所有数据:) print(df_time[2023-01])8.2 时间重采样重采样是时间序列分析的重要技术# 创建更高频率的数据 hourly_dates pd.date_range(2023-01-01, periods24, freqH) hourly_data { 时间: hourly_dates, 温度: [15 5*np.sin(i/2) np.random.normal(0, 1) for i in range(24)], 湿度: [60 10*np.cos(i/3) np.random.normal(0, 3) for i in range(24)] } df_hourly pd.DataFrame(hourly_data) df_hourly.set_index(时间, inplaceTrue) print(小时数据:) print(df_hourly.head()) # 重采样为日数据 daily_mean df_hourly.resample(D).mean() print(\n按日重采样平均值:) print(daily_mean) daily_max df_hourly.resample(D).max() print(\n按日重采样最大值:) print(daily_max) # 更复杂的重采样 def custom_resample(group): return pd.Series({ 温度范围: group[温度].max() - group[温度].min(), 平均湿度: group[湿度].mean(), 数据点数: len(group) }) daily_custom df_hourly.resample(D).apply(custom_resample) print(\n自定义重采样函数:) print(daily_custom)8.3 移动窗口操作移动窗口统计用于时间序列平滑和趋势分析# 创建股票价格示例数据 dates pd.date_range(2023-01-01, periods30, freqD) prices [100 i 5*np.sin(i/2) np.random.normal(0, 3) for i in range(30)] df_stock pd.DataFrame({ 日期: dates, 收盘价: prices }) df_stock.set_index(日期, inplaceTrue) print(股票价格数据:) print(df_stock.head(10)) # 移动平均 df_stock[5日移动平均] df_stock[收盘价].rolling(window5).mean() df_stock[10日移动平均] df_stock[收盘价].rolling(window10).mean() print(\n添加移动平均后的数据:) print(df_stock.head(15)) # 其他窗口函数 df_stock[5日最大值] df_stock[收盘价].rolling(5).max() df_stock[5日最小值] df_stock[收盘价].rolling(5).min() df_stock[5日标准差] df_stock[收盘价].rolling(5).std() print(\n各种窗口统计量:) print(df_stock[[收盘价, 5日移动平均, 5日最大值, 5日最小值, 5日标准差]].head(10)) # 扩展窗口累积统计 df_stock[累积平均] df_stock[收盘价].expanding().mean() df_stock[累积最大值] df_stock[收盘价].expanding().max() print(\n扩展窗口统计:) print(df_stock[[收盘价, 累积平均, 累积最大值]].tail(10))9. 数据可视化9.1 基本绘图功能Pandas集成了Matplotlib可以方便地进行数据可视化import matplotlib.pyplot as plt # 设置中文字体 plt.rcParams[font.sans-serif] [SimHei] plt.rcParams[axes.unicode_minus] False # 创建示例数据 np.random.seed(42) months pd.date_range(2023-01, periods12, freqM) data { 月份: months, 产品A销量: np.random.randint(100, 200, 12), 产品B销量: np.random.randint(80, 180, 12), 产品C销量: np.random.randint(120, 220, 12) } df_viz pd.DataFrame(data) df_viz.set_index(月份, inplaceTrue) print(可视化数据:) print(df_viz) # 线形图 plt.figure(figsize(12, 8)) plt.subplot(2, 2, 1) df_viz.plot(kindline, title产品销量趋势) plt.ylabel(销量) # 柱状图 plt.subplot(2, 2, 2) df_viz.plot(kindbar, title月销量柱状图, alpha0.7) plt.xticks(rotation45) # 箱线图 plt.subplot(2, 2, 3) df_viz.plot(kindbox, title销量分布箱线图) # 面积图 plt.subplot(2, 2, 4) df_viz.plot(kindarea, title销量面积图, alpha0.7) plt.tight_layout() plt.show()9.2 高级可视化技巧# 创建更复杂的数据用于高级可视化 np.random.seed(123) categories [电子, 服装, 食品, 家居] quarters [Q1, Q2, Q3, Q4] # 创建多层索引数据 index pd.MultiIndex.from_product([categories, quarters], names[类别, 季度]) data { 销售额: np.random.randint(1000, 5000, 16), 利润: np.random.randint(100, 1000, 16), 增长率: np.random.uniform(-0.1, 0.3, 16) } df_advanced pd.DataFrame(data, indexindex).reset_index() print(高级可视化数据:) print(df_advanced) # 分组柱状图 pivot_sales df_advanced.pivot(index类别, columns季度, values销售额) plt.figure(figsize(10, 6)) pivot_sales.plot(kindbar, title各季度分类销售额) plt.ylabel(销售额) plt.xticks(rotation0) plt.legend(title季度) plt.tight_layout() plt.show() # 散点图矩阵需要seaborn import seaborn as sns plt.figure(figsize(10, 8)) sns.scatterplot(datadf_advanced, x销售额, y利润, hue类别, size增长率, sizes(50, 200)) plt.title(销售额vs利润按类别和增长率) plt.show() # 热力图 pivot_growth df_advanced.pivot(index类别, columns季度, values增长率) plt.figure(figsize(8, 6)) sns.heatmap(pivot_growth, annotTrue, fmt.2%, cmapRdYlGn, center0) plt.title(各季度分类增长率热力图) plt.tight_layout() plt.show()10. 性能优化与最佳实践10.1 数据操作性能优化处理大型数据集时性能优化很重要# 创建大型数据集演示性能优化 import time # 创建100万行数据 n_rows 1000000 df_large pd.DataFrame({ id: range(n_rows), category: np.random.choice([A, B, C, D], n_rows), value1: np.random.randn(n_rows), value2: np.random.randint(0, 100, n_rows) }) print(f数据集大小: {df_large.shape}) print(f内存使用: {df_large.memory_usage(deepTrue).sum() / 1024**2:.2f} MB) # 优化数据类型 def optimize_dtypes(df): result df.copy() # 优化整数类型 int_cols result.select_dtypes(include[int64]).columns for col in int_cols: result[col] pd.to_numeric(result[col], downcastinteger) # 优化浮点类型 float_cols result.select_dtypes(include[float64]).columns for col in float_cols: result[col] pd.to_numeric(result[col], downcastfloat) # 优化对象类型 obj_cols result.select_dtypes(include[object]).columns for col in obj_cols: if result[col].nunique() / len(result[col]) 0.5: # 低基数转为category result[col] result[col].astype(category) return result # 性能对比 start_time time.time() result_original df_large.groupby(category)[value1].mean() original_time time.time() - start_time df_optimized optimize_dtypes(df_large) start_time time.time() result_optimized df_