news 2026/3/25 19:19:42

Day 49:【99天精通Python】Pandas 进阶 - 数据清洗与合并

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Day 49:【99天精通Python】Pandas 进阶 - 数据清洗与合并

Day 49:【99天精通Python】Pandas 进阶 - 数据清洗与合并

前言

欢迎来到第49天!

在现实世界中,我们拿到的数据从来都不是完美的。它们可能:

  • 缺胳膊少腿:某些单元格是空的 (NaN)。
  • 脏乱差:格式不统一(日期写成文本),包含重复行。
  • 四分五裂:数据分散在多张表里(用户信息表、订单表)。

数据分析师 80% 的时间都在做数据清洗 (Data Cleaning)。只有把数据洗干净了,后续的分析和模型才有意义(Garbage In, Garbage Out)。

本节内容:

  • 处理缺失值 (isnull,dropna,fillna)
  • 处理重复值 (duplicated,drop_duplicates)
  • 数据类型转换 (astype)
  • 多表连接 (merge)
  • 数据合并 (concat)
  • 实战练习:电商订单数据清洗

一、缺失值处理 (Missing Data)

在 Pandas 中,缺失值通常显示为NaN(Not a Number) 或None

importpandasaspdimportnumpyasnp# 创建一个包含缺失值的 DataFramedf=pd.DataFrame({"Name":["Tom","Jerry","Spike",None],"Score":[88,np.nan,75,60],"City":["Beijing","Shanghai",np.nan,"Beijing"]})print(df)

1.1 检测缺失值

print(df.isnull())# 返回布尔表 (True 表示缺失)print(df.isnull().sum())# 统计每列缺失值的数量 (非常常用!)# Name 1# Score 1# City 1

1.2 删除缺失值 (Drop)

# 只要有一列是 NaN,整行删除df_clean=df.dropna()# 只有全行都是 NaN 才删除df_clean_all=df.dropna(how='all')# 删除 Score 列缺失的行 (subset 指定列)df_score_clean=df.dropna(subset=['Score'])

1.3 填充缺失值 (Fill)

删除太可惜了,我们通常会用默认值或平均值填充。

# 1. 用固定值填充 (所有 NaN 变 0)df_filled=df.fillna(0)# 2. 用字典针对不同列填充values={"Name":"Unknown","Score":df["Score"].mean(),"City":"Unknown"}df_filled_smart=df.fillna(value=values)print(df_filled_smart)

二、重复值处理

data={"Name":["Tom","Tom","Jerry"],"Age":[10,10,8]}df=pd.DataFrame(data)# 1. 检查重复 (返回布尔 Series)print(df.duplicated())# 2. 删除重复 (保留第一条)df_unique=df.drop_duplicates()print(df_unique)

三、数据类型转换

经常遇到读进来的数字是字符串类型(比如 “100”),这会导致无法计算。

df=pd.DataFrame({"Price":["100","200","300"]})# 查看类型print(df.dtypes)# Price object (即字符串)# 转换类型 (astype)df["Price"]=df["Price"].astype(int)print(df.dtypes)# Price int32

四、数据合并 (Merge & Concat)

这是 SQL 用户最熟悉的操作。

4.1 Merge (SQL Join)

根据某一列(键)将两张表左右拼接。

# 用户表df_users=pd.DataFrame({"user_id":[1,2,3],"name":["Alice","Bob","Charlie"]})# 订单表df_orders=pd.DataFrame({"order_id":[101,102,103],"user_id":[1,1,2],# user_id 是外键"amount":[50,100,200]})# 内连接 (Inner Join): 只保留两边都有的merged=pd.merge(df_orders,df_users,on="user_id",how="inner")print(merged)# order_id user_id amount name# 0 101 1 50 Alice# 1 102 1 100 Alice# 2 103 2 200 Bob# (注意:Charlie 没有订单,所以不在结果里)# 左连接 (Left Join): 保留左表所有数据merged_left=pd.merge(df_orders,df_users,on="user_id",how="left")

4.2 Concat (拼接)

简单的上下堆叠(增加行)。

df1=pd.DataFrame({"A":[1,2]})df2=pd.DataFrame({"A":[3,4]})# 上下拼接 (axis=0)result=pd.concat([df1,df2],ignore_index=True)print(result)# A# 0 1# 1 2# 2 3# 3 4

五、实战练习:电商数据清洗

假设我们有一份脏数据raw_data.csv

id,product,price,sales 1,Apple,5.0,100 2,Banana,3.5, 3,Apple,5.0,100 4,Orange,,50 5,Grape,10.0,20

任务

  1. 读取数据。
  2. 去除重复行。
  3. 填充缺失的sales(用 0 填充)。
  4. 删除price缺失的行。
  5. 计算总销售额。

代码实现

importpandasaspdfromioimportStringIO# 模拟读取 CSV (为了方便演示,直接用字符串)csv_data="""id,product,price,sales 1,Apple,5.0,100 2,Banana,3.5, 3,Apple,5.0,100 4,Orange,,50 5,Grape,10.0,20 """df=pd.read_csv(StringIO(csv_data))print("---"" 原始数据 ---"")print(df)# 1. 去重 (排除 id 列,只看内容是否重复)# keep='first': 保留第一个df=df.drop_duplicates(subset=['product','price','sales'])# 2. 填充 sales (NaN -> 0)df['sales']=df['sales'].fillna(0)# 3. 删除 price 缺失的行df=df.dropna(subset=['price'])# 4. 计算销售额# 确保类型正确 (以防万一)df['price']=df['price'].astype(float)df['sales']=df['sales'].astype(int)df['revenue']=df['price']*df['sales']print("\n---"" 清洗后数据 ---"")print(df)print(f"\n总销售额:{df['revenue'].sum()}")

六、常见问题

Q1:fillna(inplace=True)是什么意思?

很多 Pandas 方法(如fillna,drop)默认不会修改原数据,而是返回一个新的 DataFrame。

  • 写法1:df = df.fillna(0)(推荐,逻辑清晰)
  • 写法2:df.fillna(0, inplace=True)(直接修改 df,不返回)

Q2:merge时列名不一样怎么办?

如果是左表的uid和右表的user_id连接:

pd.merge(df_left,df_right,left_on="uid",right_on="user_id")

七、小结

数据清洗

缺失值

重复值

合并

isnull() 检查

dropna() 删除

fillna() 填充

drop_duplicates()

merge (横向关联 Key)

concat (纵向堆叠)

关键要点

  1. 拿到数据先看df.info()df.isnull().sum()
  2. 缺失值处理三板斧:删(dropna)、填(fillna)、插值。
  3. 多表关联用merge,一定要搞清是 Inner 还是 Left Join。

八、课后作业

  1. 用户数据清洗:创建一个 DataFrame,包含["Name", "Age", "Email"]
    • 把 Age 为空的行填为平均年龄。
    • 把 Email 为空的行删除。
    • 把 Age 列转换为整数类型。
  2. 成绩合并:有两个 CSV,math.csv(学号, 数学分) 和english.csv(学号, 英语分)。请读取并用merge将它们合并成一张总表 (学号, 数学, 英语)。
  3. 异常值检测 (挑战):在练习1的基础上,假如 Age 中混入了 200 岁的数据,请编写代码将其识别为异常值并剔除(比如保留 0-100 岁的数据)。

下节预告

Day 50:数据可视化 Matplotlib 基础- 数据洗干净了,终于可以画图了!明天我们系统学习 Matplotlib,绘制折线图、散点图和饼图。


系列导航

  • 上一篇:Day 48 - 数据分析Pandas入门
  • 下一篇:Day 50 - 数据可视化Matplotlib基础(待更新)
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/3/15 11:48:36

终极指南:轻松掌握Legacy iOS Kit,让老设备重获新生

终极指南:轻松掌握Legacy iOS Kit,让老设备重获新生 【免费下载链接】Legacy-iOS-Kit An all-in-one tool to downgrade/restore, save SHSH blobs, and jailbreak legacy iOS devices 项目地址: https://gitcode.com/gh_mirrors/le/Legacy-iOS-Kit …

作者头像 李华
网站建设 2026/3/14 13:17:59

不用再写环境配置!BSHM镜像直接开跑

不用再写环境配置!BSHM镜像直接开跑 随着图像处理技术的快速发展,人像抠图在电商、视频制作、虚拟现实等场景中变得越来越重要。然而,传统的人像抠图模型部署过程复杂,依赖繁多,尤其是面对 TensorFlow 1.x 与现代 GPU…

作者头像 李华
网站建设 2026/3/15 11:38:57

接地电阻柜适配广泛

接地电阻柜是电力系统核心的接地保护设备,核心作用是通过在系统中性点与大地之间接入限流电阻,实现故障防护与系统稳定保障。其核心构成包括特种合金电阻器、绝缘支撑件、电流互感器、智能监控装置及金属防护柜体,其中电阻器采用耐高温、抗氧…

作者头像 李华
网站建设 2026/3/19 10:58:04

MinerU教育场景应用:试卷数字化系统搭建保姆级教程

MinerU教育场景应用:试卷数字化系统搭建保姆级教程 1. 引言 1.1 教育数字化转型的迫切需求 随着教育信息化进程的不断推进,传统纸质试卷的管理与复用面临诸多挑战。教师在日常教学中需要频繁整理历年真题、模拟卷和课堂练习,而这些资料大多…

作者头像 李华
网站建设 2026/3/20 8:41:01

Hunyuan翻译精度提升:WMT25测试集优化部署案例

Hunyuan翻译精度提升:WMT25测试集优化部署案例 1. 引言:轻量级多语翻译模型的工程挑战 随着全球化内容消费的增长,高质量、低延迟的多语言翻译需求在移动端和边缘设备场景中日益凸显。传统大模型虽具备较强翻译能力,但受限于显存…

作者头像 李华