在日常数据处理工作中,我们经常需要处理各种结构化数据,比如Excel表格、CSV文件或数据库查询结果。传统的手工操作不仅效率低下,还容易出错。Pandas作为Python最强大的数据处理库,能够帮助我们高效完成数据清洗、分析和可视化任务。本文将带你从零开始系统学习Pandas,通过58个核心知识点全面掌握这个强大的工具。
无论你是刚接触Python的新手,还是有一定编程基础想要提升数据处理能力的开发者,本教程都会从最基础的环境搭建讲起,逐步深入到高级应用场景。学完后你将能够独立完成复杂的数据分析项目,为后续的机器学习、数据可视化等进阶内容打下坚实基础。
1. Pandas基础概念与环境搭建
1.1 什么是Pandas
Pandas是一个开源的Python数据分析库,提供了快速、灵活、易用的数据结构,旨在使"关系"或"标记"数据的使用既简单又直观。它的名字来源于"Panel Data"(面板数据)的缩写,主要功能包括:
- 数据读取和写入多种格式文件(CSV、Excel、SQL等)
- 数据清洗和预处理
- 数据转换和重塑
- 数据聚合和分组运算
- 时间序列处理
Pandas最核心的两个数据结构是Series(一维数据)和DataFrame(二维数据表),这些数据结构建立在NumPy数组之上,但提供了更丰富的功能和更直观的操作接口。
1.2 环境安装与配置
在开始学习Pandas之前,我们需要先搭建合适的开发环境。推荐使用Anaconda发行版,它已经包含了Pandas及其依赖库。
Windows系统安装步骤:
# 下载Anaconda安装包(Python 3.9+版本) # 访问官网:https://www.anaconda.com/products/distribution # 运行安装程序,勾选"Add Anaconda to my PATH environment variable" # 验证安装 conda --version python --version # 安装Pandas(如果使用Anaconda,Pandas通常已预装) conda install pandas # 或者使用pip安装 pip install pandas验证安装成功:
# 在Python交互环境中测试 import pandas as pd print(pd.__version__) # 应该输出类似:1.5.01.3 开发工具选择
对于Pandas学习,推荐使用Jupyter Notebook或VS Code:
- Jupyter Notebook:适合交互式学习,可以分段执行代码并立即查看结果
- VS Code:功能强大的代码编辑器,配合Python插件体验良好
安装Jupyter Notebook:
pip install jupyterlab jupyter lab2. Series数据结构详解
2.1 创建Series对象
Series是Pandas中最基本的一维数据结构,类似于带标签的数组。
import pandas as pd import numpy as np # 从列表创建Series s1 = pd.Series([1, 3, 5, np.nan, 6, 8]) print("基本Series:") print(s1) # 从字典创建Series(字典的键成为索引) s2 = pd.Series({'a': 1, 'b': 2, 'c': 3}) print("\n从字典创建:") print(s2) # 指定索引和数据类型 s3 = pd.Series([10, 20, 30], index=['x', 'y', 'z'], dtype=float) print("\n指定索引和类型:") print(s3)2.2 Series基本操作
Series支持类似NumPy数组的操作,同时具备标签索引功能。
# 创建示例Series data = pd.Series([10, 20, 30, 40, 50], index=['a', 'b', 'c', 'd', 'e']) # 访问数据 print("第一个元素:", data[0]) # 位置索引 print("索引a的值:", data['a']) # 标签索引 print("前三个元素:\n", data[:3]) # 切片操作 # 基本统计 print("平均值:", data.mean()) print("总和:", data.sum()) print("最大值:", data.max()) # 向量化运算 print("每个元素加5:\n", data + 5) print("每个元素平方:\n", data ** 2)2.3 Series索引与切片高级技巧
Pandas提供了灵活的索引方式,包括位置索引、标签索引和布尔索引。
# 创建包含多种数据类型的Series s = pd.Series([100, 200, 300, 400, 500], index=['苹果', '香蕉', '橙子', '葡萄', '西瓜']) # 多种索引方式 print("位置索引:", s[2]) # 300 print("标签索引:", s['香蕉']) # 200 print("位置切片:", s[1:4]) # 香蕉到葡萄 print("标签切片:", s['香蕉':'葡萄']) # 包含结束位置 # 布尔索引(条件筛选) print("大于250的水果:\n", s[s > 250]) print("索引包含'葡'的水果:\n", s[s.index.str.contains('葡')]) # 花式索引 print("选择特定元素:\n", s[['苹果', '橙子', '西瓜']])3. DataFrame核心操作
3.1 创建和查看DataFrame
DataFrame是Pandas最重要的二维表格数据结构,由行索引和列索引组成。
# 从字典创建DataFrame data = { '姓名': ['张三', '李四', '王五', '赵六'], '年龄': [25, 30, 35, 28], '城市': ['北京', '上海', '广州', '深圳'], '薪资': [15000, 20000, 18000, 22000] } df = pd.DataFrame(data) print("原始DataFrame:") print(df) # 查看数据基本信息 print("\n数据形状:", df.shape) print("列名:", df.columns.tolist()) print("索引:", df.index.tolist()) # 查看数据前几行和后几行 print("\n前2行:") print(df.head(2)) print("\n后2行:") print(df.tail(2))3.2 数据选择与筛选
DataFrame提供了多种数据选择方法,满足不同场景需求。
# 选择单列(返回Series) ages = df['年龄'] print("年龄列:") print(ages) # 选择多列(返回DataFrame) subset = df[['姓名', '薪资']] print("\n姓名和薪资列:") print(subset) # 使用loc基于标签选择 print("\n选择前两行的姓名和城市:") print(df.loc[0:1, ['姓名', '城市']]) # 使用iloc基于位置选择 print("\n选择第1-2行,第0-2列:") print(df.iloc[0:2, 0:2]) # 条件筛选 high_salary = df[df['薪资'] > 18000] print("\n薪资大于18000的员工:") print(high_salary) # 多条件筛选 beijing_young = df[(df['城市'] == '北京') & (df['年龄'] < 30)] print("\n北京且年龄小于30的员工:") print(beijing_young)3.3 数据增删改操作
掌握数据的增删改是数据处理的基础技能。
# 添加新列 df['年薪'] = df['薪资'] * 12 df['等级'] = ['A', 'B', 'A', 'C'] print("添加新列后:") print(df) # 修改数据 df.loc[df['城市'] == '北京', '城市'] = '北京市' print("\n修改北京为北京市后:") print(df) # 删除列 df_drop = df.drop('等级', axis=1) # axis=1表示列 print("\n删除等级列后:") print(df_drop) # 删除行 df_drop_row = df.drop(2) # 删除索引为2的行 print("\n删除索引2的行后:") print(df_drop_row) # 插入列 df.insert(2, '工龄', [3, 5, 8, 4]) # 在第2列位置插入工龄列 print("\n插入工龄列后:") print(df)4. 数据清洗与预处理
4.1 处理缺失值
真实数据中经常存在缺失值,Pandas提供了丰富的处理方法。
# 创建包含缺失值的数据 data = { 'A': [1, 2, np.nan, 4], 'B': [5, np.nan, np.nan, 8], 'C': [10, 11, 12, 13] } df = pd.DataFrame(data) print("原始数据:") print(df) # 检测缺失值 print("\n缺失值统计:") print(df.isnull().sum()) print("\n每行缺失值数量:") print(df.isnull().sum(axis=1)) # 删除缺失值 df_dropna = df.dropna() # 删除包含缺失值的行 print("\n删除缺失值后:") print(df_dropna) # 填充缺失值 df_fillna = df.fillna({'A': df['A'].mean(), 'B': 0}) # 不同列用不同值填充 print("\n填充缺失值后:") print(df_fillna) # 向前填充/向后填充 df_ffill = df.ffill() # 用前一个有效值填充 print("\n向前填充后:") print(df_ffill)4.2 数据去重与类型转换
确保数据唯一性和正确类型是数据质量的重要保障。
# 创建包含重复值的数据 data = { '姓名': ['张三', '李四', '张三', '王五', '李四'], '部门': ['技术部', '销售部', '技术部', '人事部', '销售部'], '分数': [85, 90, 85, 88, 90] } df = pd.DataFrame(data) print("原始数据:") print(df) # 检测重复行 print("\n重复行统计:") print(df.duplicated().sum()) # 删除重复行 df_drop_duplicates = df.drop_duplicates() print("\n去重后:") print(df_drop_duplicates) # 基于特定列去重 df_drop_name = df.drop_duplicates(subset=['姓名']) print("\n按姓名去重后:") print(df_drop_name) # 数据类型转换 df['分数'] = df['分数'].astype(float) # 转换为浮点数 df['入职日期'] = pd.to_datetime(['2022-01-01', '2021-06-15', '2022-01-01', '2020-03-20', '2021-06-15']) print("\n类型转换后:") print(df.dtypes)4.3 数据标准化与编码
机器学习模型通常需要数值型数据,需要进行适当的编码转换。
# 创建包含分类数据的数据集 data = { '产品': ['手机', '电脑', '平板', '手机', '电脑'], '颜色': ['红色', '蓝色', '银色', '黑色', '蓝色'], '价格': [5000, 8000, 4000, 5500, 7500], '销量': [100, 50, 80, 120, 60] } df = pd.DataFrame(data) print("原始数据:") print(df) # 哑变量编码(One-Hot Encoding) df_encoded = pd.get_dummies(df, columns=['颜色'], prefix='颜色') print("\n颜色列哑变量编码后:") print(df_encoded) # 标签编码(Label Encoding) from sklearn.preprocessing import LabelEncoder le = LabelEncoder() df['产品编码'] = le.fit_transform(df['产品']) print("\n产品列标签编码后:") print(df) # 数据标准化(归一化) from sklearn.preprocessing import MinMaxScaler scaler = MinMaxScaler() df[['价格标准化', '销量标准化']] = scaler.fit_transform(df[['价格', '销量']]) print("\n数值列标准化后:") print(df[['价格', '价格标准化', '销量', '销量标准化']])5. 数据分组与聚合
5.1 分组操作基础
分组聚合是数据分析的核心功能,能够对数据进行分层统计。
# 创建销售数据 data = { '销售员': ['张三', '李四', '王五', '张三', '李四', '王五', '张三', '李四'], '产品类别': ['电子', '电子', '电子', '服装', '服装', '服装', '家居', '家居'], '销售额': [5000, 6000, 4500, 3000, 4000, 3500, 2000, 2500], '季度': ['Q1', 'Q1', 'Q1', 'Q2', 'Q2', 'Q2', 'Q3', 'Q3'] } df = pd.DataFrame(data) print("销售数据:") print(df) # 基本分组操作 grouped = df.groupby('销售员') print("\n按销售员分组后的组别:") print(grouped.groups) # 分组聚合计算 sales_sum = grouped['销售额'].sum() print("\n每个销售员的总销售额:") print(sales_sum) # 多列分组 multi_group = df.groupby(['销售员', '产品类别'])['销售额'].sum() print("\n按销售员和产品类别分组的总销售额:") print(multi_group)5.2 高级聚合函数
Pandas提供了丰富的聚合函数,满足复杂分析需求。
# 多种聚合函数同时计算 agg_result = df.groupby('销售员')['销售额'].agg(['sum', 'mean', 'count', 'max', 'min']) print("销售员销售额统计:") print(agg_result) # 对不同列使用不同聚合函数 detailed_agg = df.groupby('销售员').agg({ '销售额': ['sum', 'mean'], '产品类别': 'count' }) print("\n详细统计信息:") print(detailed_agg) # 自定义聚合函数 def sales_range(series): return series.max() - series.min() custom_agg = df.groupby('销售员')['销售额'].agg(['sum', sales_range]) print("\n自定义聚合结果:") print(custom_agg) # 分组后应用复杂函数 def top_sales(group): return group.nlargest(1, '销售额') top_sales_per_group = df.groupby('产品类别').apply(top_sales) print("\n每个产品类别的最高销售额记录:") print(top_sales_per_group)5.3 数据透视表
数据透视表是Excel中强大的功能,Pandas也提供了类似实现。
# 创建更丰富的销售数据 np.random.seed(42) data = { '地区': np.random.choice(['华北', '华东', '华南'], 100), '产品': np.random.choice(['手机', '电脑', '平板'], 100), '销售员': np.random.choice(['张三', '李四', '王五', '赵六'], 100), '销售额': np.random.randint(1000, 10000, 100), '月份': np.random.choice(['1月', '2月', '3月', '4月'], 100) } df = pd.DataFrame(data) print("销售数据集前10行:") print(df.head(10)) # 基本数据透视表 pivot1 = pd.pivot_table(df, values='销售额', index='地区', columns='产品', aggfunc='sum') print("\n各地区各产品总销售额透视表:") print(pivot1) # 多级索引透视表 pivot2 = pd.pivot_table(df, values='销售额', index=['地区', '销售员'], columns='月份', aggfunc=['sum', 'mean']) print("\n多级透视表:") print(pivot2) # 添加边际汇总 pivot3 = pd.pivot_table(df, values='销售额', index='地区', columns='产品', aggfunc='sum', margins=True, margins_name='总计') print("\n带总计的透视表:") print(pivot3) # 多值聚合透视表 pivot4 = pd.pivot_table(df, values='销售额', index='地区', aggfunc=['sum', 'mean', 'count']) print("\n多聚合函数透视表:") print(pivot4)6. 时间序列处理
6.1 时间索引创建与操作
时间序列分析是Pandas的强项,特别是在金融和物联网领域。
# 创建时间序列数据 dates = pd.date_range('2023-01-01', periods=100, freq='D') ts_data = pd.Series(np.random.randn(100).cumsum(), index=dates) print("时间序列数据前10行:") print(ts_data.head(10)) # 创建包含时间索引的DataFrame df_time = pd.DataFrame({ '温度': np.random.randint(15, 35, 100), '湿度': np.random.randint(30, 90, 100), '销量': np.random.randint(50, 200, 100) }, index=dates) print("\n时间索引DataFrame:") print(df_time.head()) # 时间索引操作 print("\n索引类型:", type(df_time.index)) print("时间范围:", df_time.index.min(), "到", df_time.index.max()) # 按时间筛选 jan_data = df_time['2023-01'] # 选择1月份数据 print("\n1月份数据形状:", jan_data.shape) # 时间重采样(降采样) weekly_mean = df_time.resample('W').mean() # 按周平均 print("\n周平均数据:") print(weekly_mean.head()) # 时间重采样(升采样) daily_interpolated = weekly_mean.resample('D').interpolate() # 插值到日频 print("\n日频插值数据前10行:") print(daily_interpolated.head(10))6.2 时间序列特征工程
从时间序列中提取有意义的特征是数据分析的关键步骤。
# 创建更复杂的时间序列 np.random.seed(42) dates = pd.date_range('2023-01-01', periods=365, freq='D') sales_data = pd.DataFrame({ '销售额': np.random.poisson(1000, 365) + np.sin(np.arange(365) * 2 * np.pi / 365) * 200 + # 季节性 np.arange(365) * 0.5, # 趋势 '客单价': np.random.normal(150, 20, 365) }, index=dates) print("销售时间序列前10行:") print(sales_data.head(10)) # 提取时间特征 sales_data['年份'] = sales_data.index.year sales_data['月份'] = sales_data.index.month sales_data['星期'] = sales_data.index.dayofweek sales_data['季度'] = sales_data.index.quarter sales_data['是否周末'] = sales_data.index.dayofweek.isin([5, 6]).astype(int) print("\n添加时间特征后:") print(sales_data.head()) # 滚动窗口统计 sales_data['7日均值'] = sales_data['销售额'].rolling(window=7).mean() sales_data['30日总和'] = sales_data['销售额'].rolling(window=30).sum() sales_data['7日标准差'] = sales_data['销售额'].rolling(window=7).std() print("\n滚动统计后:") print(sales_data[['销售额', '7日均值', '30日总和']].head(10)) # 时间差计算 sales_data['日环比'] = sales_data['销售额'].pct_change() # 日环比增长率 sales_data['周同比'] = sales_data['销售额'].pct_change(periods=7) # 周同比增长率 print("\n增长率计算后:") print(sales_data[['销售额', '日环比', '周同比']].head(10))7. 数据可视化集成
7.1 基础图表绘制
Pandas集成了Matplotlib,可以快速绘制各种统计图表。
import matplotlib.pyplot as plt # 设置中文字体 plt.rcParams['font.sans-serif'] = ['SimHei'] plt.rcParams['axes.unicode_minus'] = False # 创建示例数据 data = { '城市': ['北京', '上海', '广州', '深圳', '杭州', '成都'], '人口(万)': [2189, 2428, 1868, 1756, 1194, 2094], 'GDP(亿元)': [36103, 38701, 25019, 27670, 16106, 17717], '平均房价(元/㎡)': [65000, 72000, 45000, 55000, 38000, 18000] } df = pd.DataFrame(data) # 条形图 plt.figure(figsize=(10, 6)) df.set_index('城市')['人口(万)'].plot(kind='bar', color='skyblue') plt.title('各城市人口对比') plt.ylabel('人口(万)') plt.tight_layout() plt.show() # 散点图 plt.figure(figsize=(8, 6)) plt.scatter(df['人口(万)'], df['GDP(亿元)'], s=df['平均房价(元/㎡)']/1000, alpha=0.6) plt.xlabel('人口(万)') plt.ylabel('GDP(亿元)') plt.title('人口与GDP关系(气泡大小表示房价)') for i, city in enumerate(df['城市']): plt.annotate(city, (df['人口(万)'][i], df['GDP(亿元)'][i])) plt.show() # 箱线图 plt.figure(figsize=(8, 6)) df[['人口(万)', 'GDP(亿元)', '平均房价(元/㎡)']].boxplot() plt.title('数据分布箱线图') plt.xticks(rotation=45) plt.tight_layout() plt.show()7.2 时间序列可视化
时间序列数据的可视化有助于发现趋势和模式。
# 创建时间序列数据 np.random.seed(42) dates = pd.date_range('2023-01-01', periods=365, freq='D') ts_df = pd.DataFrame({ '销售额': np.cumsum(np.random.randn(365)) + 1000, '客流量': np.cumsum(np.random.randn(365)) + 500, '转化率': np.random.uniform(0.1, 0.3, 365) }, index=dates) # 折线图 plt.figure(figsize=(12, 8)) plt.subplot(3, 1, 1) ts_df['销售额'].plot(title='销售额趋势', color='blue') plt.ylabel('销售额') plt.subplot(3, 1, 2) ts_df['客流量'].plot(title='客流量趋势', color='green') plt.ylabel('客流量') plt.subplot(3, 1, 3) ts_df['转化率'].plot(title='转化率趋势', color='red') plt.ylabel('转化率') plt.tight_layout() plt.show() # 移动平均可视化 plt.figure(figsize=(12, 6)) ts_df['销售额'].plot(label='原始数据', alpha=0.5) ts_df['销售额'].rolling(window=30).mean().plot(label='30日移动平均', linewidth=2) ts_df['销售额'].rolling(window=7).mean().plot(label='7日移动平均', linewidth=2) plt.title('销售额及其移动平均') plt.legend() plt.show() # 季节性分析 ts_df['月份'] = ts_df.index.month monthly_avg = ts_df.groupby('月份')['销售额'].mean() plt.figure(figsize=(10, 6)) monthly_avg.plot(kind='bar', color='lightcoral') plt.title('各月平均销售额') plt.xlabel('月份') plt.ylabel('平均销售额') plt.show()8. 文件读写操作
8.1 常见文件格式读写
Pandas支持多种数据格式的读写,这是数据处理的基础。
# 创建示例数据 data = { '员工ID': [101, 102, 103, 104, 105], '姓名': ['张三', '李四', '王五', '赵六', '钱七'], '部门': ['技术部', '销售部', '技术部', '人事部', '财务部'], '薪资': [15000, 12000, 18000, 10000, 13000], '入职日期': ['2020-01-15', '2019-06-20', '2021-03-10', '2018-11-05', '2022-02-28'] } df = pd.DataFrame(data) # 保存为CSV文件 df.to_csv('employee_data.csv', index=False, encoding='utf-8-sig') print("CSV文件保存成功") # 读取CSV文件 df_csv = pd.read_csv('employee_data.csv', parse_dates=['入职日期']) print("从CSV读取的数据:") print(df_csv) # 保存为Excel文件 with pd.ExcelWriter('employee_data.xlsx') as writer: df.to_excel(writer, sheet_name='员工信息', index=False) # 可以保存多个sheet df.groupby('部门')['薪资'].mean().to_excel(writer, sheet_name='部门平均薪资') print("Excel文件保存成功") # 读取Excel文件 df_excel = pd.read_excel('employee_data.xlsx', sheet_name='员工信息') print("从Excel读取的数据:") print(df_excel) # JSON格式读写 df.to_json('employee_data.json', orient='records', force_ascii=False) df_json = pd.read_json('employee_data.json') print("JSON文件数据:") print(df_json)8.2 大数据集处理技巧
处理大型数据集时需要特殊技巧来提高效率。
# 分块读取大文件 def process_large_csv(file_path, chunk_size=10000): """分块处理大型CSV文件""" results = [] for chunk in pd.read_csv(file_path, chunksize=chunk_size): # 对每个数据块进行处理 chunk_processed = chunk[chunk['薪资'] > 10000] # 示例过滤条件 results.append(chunk_processed) # 合并处理结果 return pd.concat(results, ignore_index=True) # 选择合适的数据类型节省内存 def optimize_memory_usage(df): """优化DataFrame内存使用""" original_memory = df.memory_usage(deep=True).sum() # 优化数值列类型 for col in df.select_dtypes(include=['int']).columns: df[col] = pd.to_numeric(df[col], downcast='integer') for col in df.select_dtypes(include=['float']).columns: df[col] = pd.to_numeric(df[col], downcast='float') # 优化对象类型列 for col in df.select_dtypes(include=['object']).columns: if df[col].nunique() / len(df) < 0.5: # 唯一值比例小于50% df[col] = df[col].astype('category') optimized_memory = df.memory_usage(deep=True).sum() print(f"内存使用从 {original_memory} 优化到 {optimized_memory}") return df # 应用内存优化 df_optimized = optimize_memory_usage(df.copy()) print("优化后的数据类型:") print(df_optimized.dtypes)9. 性能优化与高级技巧
9.1 向量化操作优化
避免循环,使用Pandas的向量化操作可以大幅提升性能。
# 创建大型数据集用于性能测试 np.random.seed(42) large_df = pd.DataFrame({ 'A': np.random.rand(100000), 'B': np.random.rand(100000), 'C': np.random.randint(1, 100, 100000) }) # 错误的循环方式(慢) def slow_calculation(df): result = [] for i in range(len(df)): if df.loc[i, 'A'] > 0.5: result.append(df.loc[i, 'B'] * df.loc[i, 'C']) else: result.append(0) return result # 正确的向量化方式(快) def fast_calculation(df): return np.where(df['A'] > 0.5, df['B'] * df['C'], 0) # 性能对比 import time start = time.time() slow_result = slow_calculation(large_df) print(f"循环方式耗时: {time.time() - start:.4f}秒") start = time.time() fast_result = fast_calculation(large_df) print(f"向量化方式耗时: {time.time() - start:.4f}秒") # 使用apply函数(中等速度) def custom_function(row): return row['B'] * row['C'] if row['A'] > 0.5 else 0 start = time.time() apply_result = large_df.apply(custom_function, axis=1) print(f"Apply方式耗时: {time.time() - start:.4f}秒")9.2 内存优化技巧
处理大数据集时,内存管理尤为重要。
# 查看内存使用情况 def analyze_memory(df, name=""): memory_per_column = df.memory_usage(deep=True) total_memory = memory_per_column.sum() print(f"{name} 总内存使用: {total_memory / 1024 ** 2:.2f} MB") print("各列内存使用:") for col, memory in memory_per_column.items(): print(f" {col}: {memory / 1024 ** 2:.2f} MB") analyze_memory(large_df, "原始数据") # 内存优化策略 def optimize_dataframe(df): # 创建优化后的副本 df_opt = df.copy() # 整数列优化 int_cols = df_opt.select_dtypes(include=['int']).columns for col in int_cols: df_opt[col] = pd.to_numeric(df_opt[col], downcast='integer') # 浮点数列优化 float_cols = df_opt.select_dtypes(include=['float']).columns for col in float_cols: df_opt[col] = pd.to_numeric(df_opt[col], downcast='float') # 对象类型列优化 obj_cols = df_opt.select_dtypes(include=['object']).columns for col in obj_cols: num_unique = df_opt[col].nunique() num_total = len(df_opt[col]) if num_unique / num_total < 0.5: # 分类数据 df_opt[col] = df_opt[col].astype('category') return df_opt # 应用优化 optimized_df = optimize_dataframe(large_df) analyze_memory(optimized_df, "优化后数据") # 稀疏数据优化 def optimize_sparse_data(df, sparse_threshold=0.8): """优化稀疏数据(包含大量0或NaN的数据)""" df_sparse = df.copy() for col in df_sparse.columns: if df_sparse[col].dtype in ['float64', 'int64']: # 计算稀疏度 sparse_ratio = (df_sparse[col] == 0).mean() if sparse_ratio > sparse_threshold: df_sparse[col] = pd.arrays.SparseArray(df_sparse[col]) return df_sparse # 创建稀疏数据测试 sparse_data = pd.DataFrame({ 'sparse_col': [0] * 90000 + list(range(10000)) # 90%为0 }) optimized_sparse = optimize_sparse_data(sparse_data) analyze_memory(sparse_data, "原始稀疏数据") analyze_memory(optimized_sparse, "优化稀疏数据")10. 实战项目:电商数据分析
10.1 项目背景与数据准备
通过一个完整的电商数据分析项目,综合运用Pandas的各项功能。
# 创建模拟电商数据集 np.random.seed(42) n_records = 10000 # 生成模拟数据 data = { '订单ID': range(100000, 100000 + n_records), '用户ID': np.random.randint(1000, 5000, n_records), '产品类别': np.random.choice(['电子产品', '服装', '家居', '食品', '图书'], n_records), '产品价格': np.random.uniform(10, 1000, n_records), '购买数量': np.random.randint(1, 5, n_records), '购买日期': pd.date_range('2023-01-01', periods=n_records, freq='H')[:n_records], '城市': np.random.choice(['北京', '上海', '广州', '深圳', '杭州', '成都'], n_records), '支付方式': np.random.choice(['支付宝', '微信', '信用卡', '银联'], n_records) } df_orders = pd.DataFrame(data) df_orders['销售额'] = df_orders['产品价格'] * df_orders['购买数量'] print("电商订单数据前10行:") print(df_orders.head(10)) print(f"\n数据集形状: {df_orders.shape}") print("\n数据基本信息:") print(df_orders.info())10.2 数据探索性分析
对电商数据进行多维度探索,发现业务洞察。
# 基本统计描述 print("数值列统计描述:") print(df_orders[['产品价格', '购买数量', '销售额']].describe()) # 分类数据分布 print("\n产品类别分布:") print(df_orders['产品类别'].value_counts()) print("\n城市分布:") print(df_orders['城市'].value_counts()) print("\n支付方式分布:") print(df_orders['支付方式'].value_counts()) # 时间维度分析 df_orders['购买小时'] = df_orders['购买日期'].dt.hour df_orders['购买星期'] = df_orders['购买日期'].dt.dayofweek df_orders['购买月份'] = df_orders['购买日期'].dt.month # 小时销售分布 hourly_sales = df_orders.groupby('购买小时')['销售额'].sum() print("\n各小时销售额:") print(hourly_sales) # 用户行为分析 user_behavior = df_orders.groupby('用户ID').agg({ '订单ID': 'count', '销售额': 'sum', '产品类别': lambda x: x.nunique() }).rename(columns={'订单ID': '订单数', '产品类别': '购买品类数'}) print("\n用户行为分析前10名:") print(user_behavior.nlargest(10, '销售额'))10.3 高级分析与可视化
使用高级分析技术深入挖掘数据价值。
import matplotlib.pyplot as plt import seaborn as sns # 设置可视化风格 plt.style.use('seaborn-v0_8') sns.set_palette("husl") # 1. 销售额时间趋势 plt.figure(figsize=(15, 10)) # 日销售额趋势 daily_sales = df_orders.set_index('购买日期')['销售额'].resample('D').sum() plt.subplot(2, 2,