21. 数据去重与重命名
1. 概述
数据去重和重命名是数据清洗中的常用操作。去重用于删除重复记录,重命名用于修改列名或索引名,使数据更易于理解和处理。
importpandasaspdimportnumpyasnp# 创建示例数据df=pd.DataFrame({'姓名':['张三','李四','王五','张三','赵六','李四'],'年龄':[25,30,28,25,32,30],'城市':['北京','上海','广州','北京','深圳','上海'],'工资':[8000,12000,10000,8000,15000,12000]})print("原始数据:")print(df)2. 数据去重
2.1 检测重复
# 检测完全重复的行print("完全重复检测:")print(df.duplicated())# 基于指定列检测重复print("\n基于'姓名'检测重复:")print(df.duplicated(subset=['姓名']))# 标记所有重复(包括第一次)print("\n标记所有重复:")print(df.duplicated(keep=False))2.2 删除重复
# 删除完全重复(保留第一次)print("删除完全重复:")print(df.drop_duplicates())# 基于姓名去重print("\n基于姓名去重:")print(df.drop_duplicates(subset=['姓名']))# 保留最后一次出现print("\n保留最后一次:")print(df.drop_duplicates(subset=['姓名'],keep='last'))# 删除所有重复(只保留唯一值)print("\n删除所有重复:")print(df.drop_duplicates(subset=['姓名'],keep=False))2.3 去重后聚合
# 去重后保留最大值df_max=df.sort_values('工资',ascending=False).drop_duplicates(subset=['姓名'])print("保留最高工资:")print(df_max)# 去重后求和df_sum=df.groupby('姓名').agg({'年龄':'first','城市':'first','工资':'sum'}).reset_index()print("\n聚合求和:")print(df_sum)3. 重命名列
3.1 使用 rename() 方法
# 重命名单个列df_renamed=df.rename(columns={'姓名':'name','年龄':'age'})print("重命名单个列:")print(df_renamed.columns.tolist())# 重命名多个列df_renamed=df.rename(columns={'姓名':'name','年龄':'age','城市':'city','工资':'salary'})print("\n重命名多个列:")print(df_renamed.columns.tolist())# 原地修改df.rename(columns={'姓名':'name'},inplace=True)print("\n原地修改后:")print(df.columns.tolist())3.2 批量重命名
# 恢复列名df.rename(columns={'name':'姓名'},inplace=True)# 使用字典推导式批量添加前缀new_columns={col:f'col_{col}'forcolindf.columns}df_prefixed=df.rename(columns=new_columns)print("批量添加前缀:")print(df_prefixed.columns.tolist())# 批量添加后缀new_columns={col:f'{col}_字段'forcolindf.columns}df_suffixed=df.rename(columns=new_columns)print("\n批量添加后缀:")print(df_suffixed.columns.tolist())3.3 直接修改 columns 属性
# 直接赋值修改所有列名df_copy=df.copy()df_copy.columns=['A','B','C','D']print("直接修改列名:")print(df_copy.columns.tolist())# 使用列表推导式修改df_copy.columns=[col.upper()forcolindf_copy.columns]print("\n转为大写:")print(df_copy.columns.tolist())# 去除空格df_space=pd.DataFrame({' 姓名 ':[1,2],' 年龄 ':[3,4]})df_space.columns=df_space.columns.str.strip()print("\n去除列名空格:")print(df_space.columns.tolist())4. 重命名索引
4.1 重命名索引名称
# 设置索引df_indexed=df.set_index('姓名')print("原始索引:")print(df_indexed)# 重命名索引名称df_indexed.index.name='员工姓名'print("\n重命名索引:")print(df_indexed)4.2 重命名索引值
# 使用 rename 重命名索引值df_indexed=df.set_index('姓名')print("原始:")print(df_indexed)df_renamed_index=df_indexed.rename(index={'张三':'张先生','李四':'李先生'})print("\n重命名索引值:")print(df_renamed_index)# 使用函数重命名df_renamed_index=df_indexed.rename(index=lambdax:f'员工_{x}')print("\n使用函数:")print(df_renamed_index)4.3 重命名多层索引
# 创建多层索引df_multi=df.set_index(['姓名','城市'])print("多层索引:")print(df_multi)# 重命名索引层级df_multi.index.names=['员工','所在地']print("\n重命名索引层级:")print(df_multi)# 使用 rename_axisdf_multi=df_multi.rename_axis(index={'员工':'姓名','所在地':'城市'})print("\n使用 rename_axis:")print(df_multi)5. 完整示例:销售数据清洗
# 创建销售数据np.random.seed(42)sales=pd.DataFrame({'订单号':[f'ORD{i:04d}'foriinrange(1,21)],'产品名称':np.random.choice(['智能手机','笔记本电脑','平板电脑','智能手表'],20),'销售金额':np.random.randint(1000,10000,20),'销售数量':np.random.randint(1,50,20),'销售地区':np.random.choice(['华北','华东','华南','西南'],20),'销售人员':np.random.choice(['张销售','李销售','王销售'],20)})# 添加重复数据sales=pd.concat([sales,sales.iloc[0:3]],ignore_index=True)print("="*60)print("销售数据去重与重命名")print("="*60)print("\n原始数据:")print(sales.head(10))# 1. 检测重复print("\n1. 重复检测:")print(f"总行数:{len(sales)}")print(f"重复行数:{sales.duplicated().sum()}")# 2. 基于订单号去重print("\n2. 基于订单号去重:")sales_unique=sales.drop_duplicates(subset=['订单号'])print(f"去重后行数:{len(sales_unique)}")# 3. 重命名列print("\n3. 重命名列:")sales_renamed=sales_unique.rename(columns={'订单号':'order_id','产品名称':'product','销售金额':'amount','销售数量':'quantity','销售地区':'region','销售人员':'salesperson'})print(sales_renamed.columns.tolist())# 4. 添加计算列sales_renamed['unit_price']=(sales_renamed['amount']/sales_renamed['quantity']).round(2)# 5. 按销售额排序print("\n4. 销售额前5名:")print(sales_renamed.nlargest(5,'amount')[['product','amount','salesperson']])# 6. 重命名索引为订单号sales_final=sales_renamed.set_index('order_id')sales_final.index.name='Order ID'print("\n5. 最终数据:")print(sales_final.head())6. 总结
| 操作 | 方法 | 示例 |
|---|---|---|
| 检测重复 | duplicated() | df.duplicated() |
| 检测重复(指定列) | duplicated(subset=[...]) | df.duplicated(subset=['姓名']) |
| 删除重复 | drop_duplicates() | df.drop_duplicates() |
| 基于列去重 | drop_duplicates(subset=[...]) | df.drop_duplicates(subset=['姓名']) |
| 保留最后出现 | keep='last' | df.drop_duplicates(keep='last') |
| 删除所有重复 | keep=False | df.drop_duplicates(keep=False) |
| 重命名列 | rename(columns={}) | df.rename(columns={'A':'a'}) |
| 批量重命名 | 字典推导式 | {col: f'new_{col}' for col in df.columns} |
| 修改 columns | df.columns = [...] | df.columns = ['A','B'] |
| 重命名索引名 | df.index.name = 'name' | df.index.name = 'ID' |
| 重命名索引值 | rename(index={}) | df.rename(index={'旧':'新'}) |
| 重命名索引层级 | rename_axis() | df.rename_axis(index={'旧':'新'}) |