李翔-大数据技术

Big data technology!

第4章 数据呈现

项目背景

在数据分析工作中,数据准备环节通常是最耗时的阶段,包括加载、清理、转换和异常处理等任务,通常占用数据分析工作者50%到80%的时间。以下是对这一过程的详细解释:

  1. 数据异常问题:

    • 数据采集异常

    • 数据传输异常

    • 数据录入异常

    • 在数据集中数据可能存在明显错误,这些错误数据被称为“脏”数据。

    • 异常数据的产生原因多种多样,主要包括:

    • 这些异常数据会对后续的数据分析、模型搭建和参数调优产生负面影响。

  2. 数据清洗的目的:

    • 数据清洗的核心目标是将原始数据集转换为高质量的数据集。

    • 清洗后的数据支持后续的统计分析和机器学习模型的建立,确保分析结果的准确性和可靠性。

  3. 数据可视化的重要性:

    • 数据可视化利用图形技术有效地解读和传达分析结果信息。

    • 通过可视化,从不同维度深入观察和分析数据,有助于揭示数据中的趋势和模式,为决策提供支持。

通过系统化的清洗和可视化,数据分析工作可以变得更加高效和可靠,为统计分析和机器学习提供坚实的基础。


4.2 技能图谱


4.3 数据清洗

数据分析与数据质量

优良的数据分析结果依赖于其输入数据集的高质量。未经处理的实际数据集通常存在各种问题,这些问题会影响数据分析的准确性和可靠性。

常见数据问题

  • 数据缺失: 数据集中缺少必要的信息,例如某些列或行中的值为空。

  • 数据格式不统一: 数据的格式不一致,例如日期格式不同、文本大小写不统一等。

  • 数据单位不统一: 数据使用不同的单位表示,例如温度可能同时使用摄氏度和华氏度。

  • 数据错误: 数据中存在明显的错误或不合理的值,例如负的年龄或超出合理范围的温度。

这些问题会导致数据集被称为“脏”数据。清洗这些“脏”数据是数据预处理中的一个重要步骤。

数据清洗功能

数据清洗是提高数据质量的重要步骤,主要包括以下功能:

  • 缺失值处理: 填充或删除缺失的数据,使数据集更完整。

  • 异常值处理: 识别并修正数据中的异常值或错误值。

  • 数据转换:


    • 下面是一个关于数据离散化的简化例子。设想我们有一组人的年龄数据如下:

      年龄:[22, 45, 19, 34, 26, 59, 38, 15, 67, 43]

      我们需要将这些年龄数据分类为三个类别:“青年”、“中年”和“老年”。采用等宽离散化方法,我们将年龄区间(15岁到70岁)划分为三个等宽区间:

      应用这个方法,年龄数据的分类结果是:

      这样,连续的年龄数据就被简单地转换成了三个明确的年龄段类别。

      为什么要“离散化”

      原因说明
      1. 简化模型连续数值太多不好分析,分成几类更容易看规律。
      2. 便于统计比如计算“各年龄段人数”、“各分数段占比”。
      3. 便于可视化离散的类别可以直接做柱状图、饼图等。
      4. 提升算法效果有些算法(如决策树)更适合处理离散特征。
    • [青年, 中年, 青年, 中年, 青年, 老年, 中年, 青年, 老年, 中年]

    • “青年”:15-33岁

    • “中年”:34-52岁

    • “老年”:53-70岁

    • “男” → 1

    • “女” → 0

    • 数据替换: 将数据中的特定值替换为其他值。

      假设我们有一列性别数据:

      ["男", "女", "男", "女", "女"]

      为了方便分析或建模,我们想把文字改成数字(机器更容易理解):

      替换后得到:

      [1, 0, 1, 0, 0]

      其他常见替换场景

      场景原始数据替换规则结果
      缺失值替换[89, 76, None, 91]None → 0[89, 76, 0, 91]
      异常值替换[12, 999, 35, 40]999 → 平均值(29)[12, 29, 35, 40]
      标准化文本["北京 ", "北京市", "Beijing"]都替换为 “北京”["北京", "北京", "北京"]
    • 数据离散化: 把一串连续的数字数据,分成几个“区间”,并给每个区间贴上一个标签,让数字变成分类。

4.3.1 处理缺失值

一、缺失值处理概述

在实际数据集中,常常会遇到某些字段的数据缺失。Pandas 提供了专门的方式来识别、处理和填补这些缺失值,从而保证后续分析的准确性。

二、NaN 的表示与原因

  • 表示方式: 在 Pandas 中,缺失值使用浮点类型NaNNot a Number)表示。这是因为 NaN 专门用于表示未定义或不可用的数值

  • 类型转换: 当一个列或数组中存在缺失值时,Pandas 会自动将该列的数据类型转换为浮点数,以便能够表示 NaN。即使数据原本是整数类型,包含 NaN 后也会转为浮点类型。

三、缺失值检测


方法作用
df.isnull()检查每个位置是否为缺失值,返回布尔 DataFrame
df.isna()  【常用】同上,两者功能完全一致
df.notnull() / df.notna()返回非缺失值位置的布尔值


四、缺失值处理方法

删除缺失值 dropna()

  • df.dropna():默认删除含缺失值的行;

  • df.dropna(axis=1):删除含缺失值的列;

  • 可通过 thresh 参数保留至少有 n 个非空值的行/列。

填充缺失值 fillna()

  • 用固定值:df.fillna(0)

  • 用列均值:df["age"].fillna(df["age"].mean())

  • 前向/后向填充:df.fillna(method="ffill") / df.fillna(method="bfill")

判断缺失值数量

  • df.isnull().sum():每列缺失值数量统计;

  • df.isnull().any():判断每列是否含有缺失值。


五、常见处理策略建议


情况建议
少量缺失可考虑删除行或列
缺失值较集中使用均值、中位数、众数等填充
时间序列数据使用前向或后向填充(ffill/bfill
特殊业务逻辑可设定默认值如 0、"未知" 等



实验任务:处理用户信息表中的缺失值(users_dirty.csv)

users_dirty.csv 是某电商平台的用户信息表,包含部分缺失字段。为了后续做用户画像、行为建模等工作,需先进行数据清洗,处理缺失值。

数据说明:

缺失值(字段 age/city/register_date):随机抽样产生空值,模拟用户未填写或系统漏录。

异常值(age 超出合理范围):注入 -10、130、180 等不合理年龄,模拟录入或采集错误。

未知值(gender = "未知"):固定 10 行性别标记为“未知”,模拟模糊性数据。

格式异常(register_date 非标准格式,未开启):注入中文日期、顺序颠倒或非法字符串,模拟不同系统或人工输入错误。

重复记录(约 0.3%):复制部分行形成重复,模拟用户重复注册或系统重复采集。

乱序数据:随机打乱数据行顺序,模拟实际业务中的无序输入。


原始数据读取

import pandas as pd

# 读取用户信息表
users = pd.read_csv("users_dirty.csv")

# 显示前5行查看结构
users.head()

【例4-1】检测哪些列存在缺失值

users.isnull().any()
# 等同于 users.isna().any()

【例4-2】统计每列缺失值数量

users.isnull().sum()
# 等同于 users.isna().sum()

【例4-3】输出含缺失值的前10行记录

# users.isnull().any(axis=1) 用来判断每一行是否存在缺失值,返回一个布尔序列(True 表示该行有缺失值)。
# axis=0 表示竖向操作(从上往下) → 针对“行”进行处理;
# axis=1 表示横向操作(从左到右) → 针对“列”进行处理。
users[users.isnull().any(axis=1)].head(10)

【例4-4】将缺失的年龄(age)填充为所有非缺失年龄的平均值

# 1.查看年龄列有缺失的行
users[users["age"].isnull()]

# 2.替换(在原表上进行修改)
users["age"].fillna(users["age"].mean(), inplace=True)

【例4-5】将 city 列缺失值填为 “默认城市”

# 1.查看有缺失的行
users[users["city"].isnull()]

# 2.替换
users["city"].fillna("默认城市", inplace=True)

【例4-6】删除注册时间(register_date)为空的用户

# 1.统计有多少个缺失值
users["register_date"].isnull().sum()

# 2.删除:dropna(subset=[...])
users = users.dropna(subset=["register_date"])

【例4-7】删除所有含缺失值的用户记录

# 1.重新读取用户信息表
users = pd.read_csv("users_dirty.csv")
# 2.统计每列缺失值数量
users.isnull().sum()
# 3.删除所有包含缺失值的行,返回一个新的“干净”表格
users_cleaned = users.dropna()

【例4-8】处理重复记录

# 1.查看是否有重复行(完全相同)
users.duplicated().sum()

# 2.查看重复行的具体内容
users[users.duplicated(keep=False)].sort_values(by="user_id")
# duplicated(keep=False):表示保留所有重复的行(不只显示后面的)。
# 如果不加 keep=False,默认只标记重复项的后面那一条。

# 3.去重
# 方法一:删除重复行,保留第一次出现的。(最常用)
users_clean = users.drop_duplicates(keep="first")

# 方法二:删除重复行,保留最后一次出现的。
users_clean = users.drop_duplicates(keep="last")

# 方法三:去重删除所有重复的(不保留任何一条)
users_clean = users.drop_duplicates(keep=False)


【例4-9】按用户ID排序,恢复顺序

# 把用户表按照 user_id 排序,并重建连续的行号索引,得到一个有序的新表 users_sorted。
# reset_index(drop=True) 的作用是——重建连续行号,丢弃旧索引,让表格更整洁。
users_sorted = users.sort_values(by="user_id").reset_index(drop=True)



4.3.2 处理异常值

处理被识别的异常值时,主要有两种方法:删除法和填充法。

  • 删除法:当异常值的数量较少或其删除对数据分布的影响较小时,删除异常值是一个较好的选择。

  • 填充法:如果异常值数量较多,或主要由读数错误、输入错误导致,采用填充法更为合适。填充方法包括:

    • 后向填充:使用前一个有效值填充缺失值,

    • 前向填充:使用后一个有效值填充缺失值,

    • 平均值填充

    • 中位数填充

    • 最大值填充

    • 最小值填充

    • 零值填充

    • 随机选择填充

根据具体情况选择合适的方法,以确保数据处理的准确性和完整性。


以下是结合 电商数据集(如 users_dirty.csv 中的用户年龄)设计的异常值处理练习题

【例4-10】使用箱型图方法,识别users表中的 age 字段中的异常值。

箱型图(boxplot),专门用来看一组数据的分布:中间集中在哪儿、上下边界大概在哪儿、有没有异常值

import matplotlib.pyplot as plt

# 正确显示中文与负号
plt.rcParams['font.sans-serif'] = ['SimHei']   # 显示中文
plt.rcParams['axes.unicode_minus'] = False     # 显示负号

# 绘制年龄的箱型图
plt.boxplot(users["age"].dropna())
plt.title("年龄字段的箱型图")
plt.ylabel("Age")
plt.show()

image-20250828160136040

结合结果

在箱型图中:


名称位置含义
下边缘(Q1)箱子的底边表示 25% 的人年龄低于这个值
中间线(Q2)[中位线]箱子中间的黄线表示 50% 的人年龄低于这个值(中位数)
上边缘(Q3)箱子的顶边表示 75% 的人年龄低于这个值
上下“胡须”线延伸线表示正常范围的最大/最小值(非异常点)
上方几个黑点、空心点上下异常值,说明确实有极端年龄被识别出来。


  • 图里箱子的主体在 30~45 岁之间(说明大多数用户年龄在这个区间)。

  • 中位数大约在 35 岁左右

  • 上方几个黑点、空心点 = 异常值,说明确实有极端年龄被识别出来。


【例4-11】读取用户表 users_dirty.csv,查看 age 字段中是否存在明显异常值(如小于 0 或大于 120)。

import pandas as pd

users = pd.read_csv("users_dirty.csv")

# 查看年龄分布的基本信息
print(users["age"].describe())

# 筛选出异常年龄数据
users[(users["age"] < 0) | (users["age"] > 120)]
# 等同于 users.query("age < 0 or age > 120")

【例4-12】删除所有年龄不合理(<0 或 >120)的用户数据。

# 删除异常年龄数据,users_cleaned = users.query("0 <= age <= 120")
users_cleaned = users[(users["age"] >= 0) & (users["age"] <= 120)]

users_cleaned.shape

【例4-13】用中位数填充所有不合理年龄(<0 或 >120)为正常范围的值。

中位数是描述数据集中间位置的统计量 ,把一组数据按大小排序后,处于中间位置的数值即为中位数。

# (1)先找出“正常年龄”的数据,并计算中位数 /miːdiən/
# 条件:年龄在 0~120 岁之间
valid_median_age = users.query("0 <= age <= 120")["age"].median()

# (2)用中位数去替换掉异常的年龄
# 如果年龄小于0 或 大于120,就用中位数代替,否则保留原值
users["age"] = users["age"].apply(
   lambda x: valid_median_age if (x < 0 or x > 120) else x
)
# apply() 会让每个年龄都交给后面的函数(lambda x: ...)去处理。
# valid_median_age if (x < 0 or x > 120) else x
#  若不合理:替换为中位数(valid_median_age)
#  若合理:保留原来的年龄 x


【例4-14】处理性别的异常值

# 查看性别列的分组及数量
users.groupby("gender").size()
# 或者:df_dirty["gender"].value_counts()

# 方法一:替换
# 把性别列中的“未知”替换为“男”
users["gender"] = users["gender"].replace("未知", "男")

# 方法二:删除
# 删除掉 gender 等于 "未知" 的行。
users = users[usres["gender"] != "未知"]
# 或者
users = users[users["gender"].isin(["男", "女"])]


4.4 数据可视化

一、Matplotlib 简介

Matplotlib 是 Python 最常用的数据可视化库,能轻松绘制折线图、柱状图、饼图、散点图等。 它常与 Pandas 搭配使用,用于把数据分析结果“画出来”,让信息更直观。


二、基本使用步骤


步骤操作示例
① 导入库import matplotlib.pyplot as pltplt 是绘图的核心对象
② 准备数据用列表、数组或 Pandas 序列x = [1,2,3]; y = [5,8,6]
③ 绘制图形调用绘图函数plt.plot(x, y)
④ 设置标题与坐标轴plt.title("标题")plt.xlabel("X轴")plt.ylabel("Y轴")增强可读性
⑤ 显示图形plt.show()必须写,否则图形不显示



三、常用图形类型


图形类型函数适用场景关键参数
折线图plt.plot(x, y)变化趋势color, marker, linestyle
柱状图plt.bar(x, y)类别对比(垂直)color, width
水平条形图plt.barh(x, y)类别较多时展示color
饼图plt.pie(values, labels=labels, autopct='%1.1f%%')占比分析startangle, colors
散点图plt.scatter(x, y)两变量关系s(点大小), c(颜色)



四、图表美化常用语法


功能语法示例说明
中文显示........plt.rcParams['font.sans-serif']=['SimHei']``plt.rcParams['axes.unicode_minus']=False显示中文与负号
图形尺寸plt.figure(figsize=(8,6))控制宽高
标题plt.title("销售趋势", fontsize=16)设置字体大小
坐标轴标签plt.xlabel("月份"); plt.ylabel("销量")
网格线plt.grid(axis='y', linestyle='--', alpha=0.6)更易读
添加数值plt.text(x, y, str(value))条形图上标数字
自动布局plt.tight_layout()防止遮挡


4.4.1 绘制条形图

image.png

4.4.2 绘制柱状图

image.png



image.png



image.png


发表评论:

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。

Powered By Z-BlogPHP 1.7.3

版权:李翔
备案/许可证编号为:新ICP备2024006115号-1