Python NumPy 数据清洗:高效处理数据异常与缺失

Python NumPy 数据清洗:高效处理数据异常与缺失

文章目录

  • Python NumPy 数据清洗:高效处理数据异常与缺失
      • 一 数据预处理的常见问题
      • 二 待处理的数据
      • 三 数据预处理
      • 四 清洗数据
        • 1 查看第一列学号
        • 2 查看第二列年龄
          • 结果解析
          • 函数解释
            • 1)`~np.isnan(data[:, 1])`
            • 2)`data[~np.isnan(data[:, 1]), 1]`
        • 3 观察后三行数据
          • 结果解析
          • 函数解释
      • 五 完整代码示例
      • 六 源码地址

本文展示了如何利用 Python 的 NumPy 库高效地进行数据清洗,特别是对复杂数据的异常处理与缺失值填补。文章详细介绍了数据清洗中的常见问题,包括数据值缺失、异常值、格式错误及非独立数据,并提供了对应的解决方案。通过具体的学期学生成绩数据示例,演示了如何识别重复学号、处理缺失年龄值、剔除异常分数、填补缺失成绩等。借助 np.uniquenp.isnannp.clip 等 NumPy 方法,实现了对数据的精细化处理。最终,经过数据清洗,所有数据均符合预期格式和规则,为后续的数据分析和建模奠定了坚实基础。

一 数据预处理的常见问题

数据值缺失数据值异常大或小格式错误非独立数据错误。以下是数据预处理中常见问题及其描述、原因和解决方法的表格:

问题类型描述产生原因解决方法
数据值缺失数据集中有些值为空或不存在,通常用 NaNnull 或空字符串表示。数据收集过程中的遗漏、传感器故障、数据传输问题。删除缺失值、填充缺失值(平均值、中位数等)、标记缺失值。
数据值异常大或小数据集中某些值与其他数据显著不同,通常为极端值或不合理的值。测量或录入错误、正态分布中的极端情况、数据采集设备问题。剔除异常值、替换异常值(中位数、分位数等)、使用算法检测异常值。
格式错误数据格式不符合预期,如字符串中混有数字、日期格式不一致、分类标签混乱等。数据来源不一致、录入错误、缺乏格式规范。统一格式、清理数据(删除或更正错误格式)、转换数据类型。
非独立数据错误数据点之间存在依赖关系,如重复数据、同一对象的多次测量导致数据非独立性。同一对象多次采样、数据重复、对象间存在依赖关系。删除重复数据、聚合处理(取平均、最大值等)、标记数据依赖性。

:在项目中,应结合业务背景和实际情况综合判断哪些数据属于异常。

二 待处理的数据

假设手上有一学期的小学生上课成绩数据。

raw_data = [
    ["Name", "StudentID", "Age", "AttendClass", "Score"],
    ["小明", 20131, 10, 1, 67],
    ["小花", 20132, 11, 1, 88],
    ["小菜", 20133, None, 1, "98"],
    ["小七", 20134, 8, 1, 110],
    ["花菜", 20134, 98, 0, None],
    ["西兰花", 20136, 12, 0, 12]
]
print(raw_data)

对比数据类型。

data = np.array(raw_data)
# object
print("data.dtype", data.dtype)
test1 = np.array([1, 2, 3])
test2 = np.array([1.1, 2.3, 3.4])
test3 = np.array([1, 2, 3], dtype=np.float64)
print("test1.dtype", test1.dtype)
print("test2.dtype", test2.dtype)
print("test3.dtype", test3.dtype)
print("test2 > 2 ", test2 > 2)
# TypeError: '>' not supported between instances of 'str' and 'int'
# print("data > 2", data > 2)  # 这里会报错

运行结结果

data.dtype object
test1.dtype int64
test2.dtype float64
test3.dtype float64
test2 > 2  [False  True  True]

NumPy 数组主要是用于存储同种数据类型的元素 ,运行 data > 2 后报错 TypeError: '>' not supported between instances of 'str' and 'int'。下面对上述 data 数据进行清洗。

三 数据预处理

不要首行字符串并去掉首列名字。

data_process = []
for i in range(len(raw_data)):
    if i == 0:
        continue  # 不要首行字符串
    # 去掉首列名字
    data_process.append(raw_data[i][1:])
data = np.array(data_process, dtype=np.float64)
print("data.dtype", data.dtype)
print(data)

四 清洗数据

1 查看第一列学号

进过 np.unique 函数运行之后,发现学号有重复,查看数据发现相邻的数据 20135,则修改第五行第一列。

# 查看第一列学号
sid = data[:, 0]
unique, counts = np.unique(sid, return_counts=True)
print(counts)
# 数据中少 20135
print(unique[counts > 1])
# 修改第五行第一列
data[4, 0] = 20135
print(data)
2 查看第二列年龄
# 查看第二列年龄
is_nan = np.isnan(data[:, 1])
print("is_nan:", is_nan)
nan_idx = np.argwhere(is_nan)
print(nan_idx)
# 用 ~ 符号可以 True/False 对调
print(~np.isnan(data[:, 1]))
# 计算有数据的平均年龄,用 ~ 符号可以 True/False 对调
print(data[~np.isnan(data[:, 1]), 1])
mean_age = data[~np.isnan(data[:, 1]), 1].mean()
print("有数据的平均年龄:", mean_age)

运行结果

is_nan: [False False  True False False False]
[[2]]
[ True  True False  True  True  True]
[10. 11.  8. 98. 12.]
有数据的平均年龄: 27.8
结果解析

发现平均均值偏高,查看数据发现有个年龄为 98 的,判断这个是异常数据,继续处理数据。

# ~ 表示 True/False 对调,& 就是逐个做 Python and 的运算
normal_age_mask = ~np.isnan(data[:, 1]) & (data[:, 1] < 20)
print("normal_age_mask:", normal_age_mask)

normal_age_mean = data[normal_age_mask, 1].mean()
print("normal_age_mean:", normal_age_mean)

data[~normal_age_mask, 1] = normal_age_mean
print("ages:", data[:, 1])

运行结果

normal_age_mask: [ True  True False  True False  True]
normal_age_mean: 10.25
ages: [10.   11.   10.25  8.   10.25 12.  ]
函数解释
1)~np.isnan(data[:, 1])
  • ~ 是按位取反运算符,它将布尔数组中 TrueFalse 的值互换,即将 True 变为 FalseFalse 变为 True
  • ~np.isnan(data[:, 1])np.isnan(data[:, 1]) 中所有的 True 变为 FalseFalse 变为 True,即标记出 data[:, 1] 中那些不是 NaN 的元素。
2)data[~np.isnan(data[:, 1]), 1]
  • 这一部分使用布尔索引选择 data 中第二列(索引为 1)的非 NaN 元素。
  • data[~np.isnan(data[:, 1]), 1] 中的 ~np.isnan(data[:, 1]) 作为行的条件,表示只选择第二列中非 NaN 对应的行。
  • 1 表示列索引,指第二列。
  • 结果是一个一维数组,包含 data 中第二列所有非 NaN 的元素。
3 观察后三行数据
# 观察后三行数据
print(data[-3:, 2:])

运行结果

[[  1. 110.]
 [  0.  nan]
 [  0.  12.]]
结果解析

因为没上课,就没成绩,但是倒数第一行,没上课,但是有成绩?倒数第三行,成绩居然超出了满分 100 分,继续处理数据。

# 没上课的转成分数转成 0
data[data[:, 2] == 0, 3] = 0
# 超过 100 分和低于 0 分的都处理一下
data[:, 3] = np.clip(data[:, 3], 0, 100)
print(data[:, 2:])
函数解释

np.clip(array, min, max):这是 NumPy 的一个函数,用于将数组中的元素限制在给定的最小值和最大值之间。对于每个元素:

  • 如果元素小于 min,则将该元素设置为 min
  • 如果元素大于 max,则将该元素设置为 max
  • 如果元素在 minmax 之间,则保持不变。

五 完整代码示例

# This is a sample Python script.

# Press ⌃R to execute it or replace it with your code.
# Press Double ⇧ to search everywhere for classes, files, tool windows, actions, and settings.
import numpy as np


def print_hi(name):
    # Use a breakpoint in the code line below to debug your script.
    print(f'Hi, {name}')  # Press ⌘F8 to toggle the breakpoint.
    raw_data = [
        ["Name", "StudentID", "Age", "AttendClass", "Score"],
        ["小明", 20131, 10, 1, 67],
        ["小花", 20132, 11, 1, 88],
        ["小菜", 20133, None, 1, "98"],
        ["小七", 20134, 8, 1, 110],
        ["花菜", 20134, 98, 0, None],
        ["西兰花", 20136, 12, 0, 12]
    ]
    # print(raw_data)

    data = np.array(raw_data)
    print("data.dtype", data.dtype)
    test1 = np.array([1, 2, 3])
    test2 = np.array([1.1, 2.3, 3.4])
    test3 = np.array([1, 2, 3], dtype=np.float64)
    print("test1.dtype", test1.dtype)
    print("test2.dtype", test2.dtype)
    print("test3.dtype", test3.dtype)
    print("test2 > 2 ", test2 > 2)
    # TypeError: '>' not supported between instances of 'str' and 'int'
    # print("data > 2", data > 2)  # 这里会报错
    # 数据预处理
    data_process = []
    for i in range(len(raw_data)):
        if i == 0:
            continue  # 不要首行字符串
        # 去掉首列名字
        data_process.append(raw_data[i][1:])
    data = np.array(data_process, dtype=np.float64)
    print("data.dtype", data.dtype)
    # print(data)
    # 清洗数据
    # 查看第一列学号
    sid = data[:, 0]
    unique, counts = np.unique(sid, return_counts=True)
    print(counts)
    # 数据中少 20135
    print(unique[counts > 1])
    # 修改第五行第一列
    data[4, 0] = 20135
    # print(data)
    # 查看第二列年龄
    is_nan = np.isnan(data[:, 1])
    print("is_nan:", is_nan)
    nan_idx = np.argwhere(is_nan)
    print(nan_idx)
    # 用 ~ 符号可以 True/False 对调
    print(~np.isnan(data[:, 1]))
    # 计算有数据的平均年龄,用 ~ 符号可以 True/False 对调
    print(data[~np.isnan(data[:, 1]), 1])
    mean_age = data[~np.isnan(data[:, 1]), 1].mean()
    print("有数据的平均年龄:", mean_age)
    # 发现平均均值偏高,查看数据发现有个年龄为 98 的,判断这个是异常数据
    # ~ 表示 True/False 对调,& 就是逐个做 Python and 的运算
    normal_age_mask = ~np.isnan(data[:, 1]) & (data[:, 1] < 20)
    print("normal_age_mask:", normal_age_mask)

    normal_age_mean = data[normal_age_mask, 1].mean()
    print("normal_age_mean:", normal_age_mean)

    data[~normal_age_mask, 1] = normal_age_mean
    print("ages:", data[:, 1])

    # 观察后面两数据
    print(data[-3:, 2:])
    # 因为没上课,就没成绩,但是倒数第一行,没上课,怎么还有成绩?还有倒数第三行,成绩居然超出了满分 100 分
    # 没上课的转成分数转成 0
    data[data[:, 2] == 0, 3] = 0

    # 超过 100 分和低于 0 分的都处理一下
    data[:, 3] = np.clip(data[:, 3], 0, 100)

    print(data[:, 2:])


# Press the green button in the gutter to run the script.
if __name__ == '__main__':
    print_hi('数据清洗')

# See PyCharm help at https://www.jetbrains.com/help/pycharm/

复制粘贴并覆盖到你的 main.py 中运行,运行结果如下。

Hi, 数据清洗
data.dtype object
test1.dtype int64
test2.dtype float64
test3.dtype float64
test2 > 2  [False  True  True]
data.dtype float64
[1 1 1 2 1]
[20134.]
is_nan: [False False  True False False False]
[[2]]
[ True  True False  True  True  True]
[10. 11.  8. 98. 12.]
有数据的平均年龄: 27.8
normal_age_mask: [ True  True False  True False  True]
normal_age_mean: 10.25
ages: [10.   11.   10.25  8.   10.25 12.  ]
[[  1. 110.]
 [  0.  nan]
 [  0.  12.]]
[[  1.  67.]
 [  1.  88.]
 [  1.  98.]
 [  1. 100.]
 [  0.   0.]
 [  0.   0.]]

六 源码地址

代码地址:

国内看 Gitee 之 numpy/数据清洗.py

国外看 GitHub 之 numpy/数据清洗.py

引用 莫烦 Python

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/884408.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

告别背锅侠!29个空场景及测试方法的实战指南

想必大家在日常的测试工作中&#xff0c;经常会碰到以下这些场景&#xff1a; 场景一&#xff1a; 测试人员&#xff1a;有一个数据为空的场景还没有验证。 研发人员&#xff1a;这个场景不会出现&#xff0c;因为没有删除逻辑。 场景二&#xff1a; 研发人员&#xff1a;…

蓝桥杯模块二:数码管的静态、动态实现

模块二训练 1.静态显示 一、数码管电路图 二、电路分析 1.数码管电路分析 端口分公共端和段码&#xff0c;先用公共端控制一个数码管&#xff0c;再用段码实现显示数字。共阳数码管公共端输入高电平&#xff0c;段码输入低电平实现点亮 2.锁存器 Y7控制段码&#xff0c;Y6控…

【含文档】基于Springboot+微信小程序 的中心医院用户移动端(含源码+数据库+lw)

1.开发环境 开发系统:Windows10/11 架构模式:MVC/前后端分离 JDK版本: Java JDK1.8 开发工具:IDEA 数据库版本: mysql5.7或8.0 数据库可视化工具: navicat 服务器: SpringBoot自带 apache tomcat 主要技术: Java,Springboot,mybatis,mysql,vue 2.视频演示地址 3.功能 系统定…

全志科技发布T536高性能智慧工业芯片,飞凌嵌入式率先推出配套核心板

2024年9月24日下午&#xff0c;全志科技在中国国际工业博览会上成功举办了其最新产品——T536高性能智慧工业芯片的全球首发发布会。这款芯片采用创新的4核Cortex-A55与RISC-V混合架构&#xff0c;主频分别达到1.6GHz和600MHz&#xff0c;并集成了2TOPS算力的NPU&#xff0c;吸…

生信初学者教程(四):软件

文章目录 RRstudioLinux系统其他软件本书是使用R语言编写的教程,用户需要下载R和RStudio软件用于进行分析。 版权归生信学习者所有,禁止商业和盗版使用,侵权必究 R R语言是一种免费的统计计算和图形化编程语言,是一种用于数据分析和统计建模的强大工具。它具有丰富的统计…

耦合微带线单元的网络参量和等效电路公式推导

文档下载链接&#xff1a;耦合微带线单元的网络参量和等效电路资源-CSDN文库https://download.csdn.net/download/lu2289504634/89583027笔者水平有限&#xff0c;错误之处欢迎留言&#xff01; 一、耦合微带线奇偶模详细推导过程 二、2,4端口开路 三、2端口短路、3端口开路 四…

智能密码、指纹锁语音芯片ic方案 可存放40s语音内容 NVD语音芯片

随着科技的飞速发展&#xff0c;智能家居安全领域迎来了前所未有的变革。智能密码与指纹锁作为现代家庭安全防护的重要一环&#xff0c;其背后的语音芯片IC开发更是这一变革中的关键技术突破。 智能密码、指纹锁语音芯片ic方案 选型与简介&#xff1a; NVD语音芯片是一款低成…

quiz: python网络爬虫之规则1

下面答错了&#xff1a; B c 8A&#xff0c; 9A

STM32F407之超声波模块使用

#include "sys.h" #include "delay.h" #include "usart.h" #include "includes.h" #include "HC_SR04.h"int main() {OS_ERR err;//错误uart_init(9600);//串口初始化//超声波初始化HC_SR04();//OS初始化 他是第一个运行的函…

【大数据】数据中台怎么样助力企业创新和客户实践

在当今数字化时代&#xff0c;数据成为了企业竞争的关键因素。企业拥有大量的数据&#xff0c;但如何高效地利用这些数据&#xff0c;实现创新和提升客户体验&#xff0c;成为了一项重要的挑战。数据中台作为一种重要的数据管理和分析工具&#xff0c;发挥着关键的作用。本文将…

大数据毕业设计选题推荐-食品销售数据分析系统-Hive-Hadoop-Spark

✨作者主页&#xff1a;IT研究室✨ 个人简介&#xff1a;曾从事计算机专业培训教学&#xff0c;擅长Java、Python、微信小程序、Golang、安卓Android等项目实战。接项目定制开发、代码讲解、答辩教学、文档编写、降重等。 ☑文末获取源码☑ 精彩专栏推荐⬇⬇⬇ Java项目 Python…

数集相等定义凸显“R各元x的对应x+1的全体=R”是几百年重大错误

黄小宁 变量x所取各数也均由x代表&#xff0c;x代表其变域&#xff08;x所有能取的数组成的集&#xff09;内任一元。设集A&#xff5b;x&#xff5d;表A各元均由x代表&#xff0c;&#xff5b;x&#xff5d;中变量x的变域是A。其余类推。因各数x可是数轴上点的坐标所以x∈R变换…

AWS Network Firewall -NAT网关配置只应许白名单域名出入站

1. 创建防火墙 选择防火墙的归属子网&#xff08;选择公有子网&#xff09; 2. 创建规则白名单域名放行 3. 绑定相关规则 继续往下拉 绑定非托管规则 4. 配置网络路由 相关规则 参考图 解释 防火墙的归属公有子网路由表规则机器实例的规则子网路由表规则nat网管路…

springboot实战学习(7)(JWT令牌的组成、JWT令牌的使用与验证)

接着上篇博客的学习。上篇博客是在基本完成用户模块的注册接口的开发以及注册时的参数合法性校验的基础上&#xff0c;基本完成用户模块的登录接口的主逻辑以及提到了问题&#xff1a;"用户未登录&#xff0c;需要通过登录&#xff0c;获取到令牌进行登录认证&#xff0c;…

Linux 安装redis主从模式+哨兵模式3台节点

下载 https://download.redis.io/releases/ 解压 tar -zxvf redis-7.2.4.tar.gz -C /opt chmod 777 -R /opt/redis-7.2.4/安装 # 编译 make # 安装&#xff0c; 一定是大写PREFIX make PREFIX/opt/redis-7.2.4/redis/ install配置为系统服务 cd /etc/systemd/system/主服务…

一文上手SpringSecuirty【六】

自定义认证流程完成之后,前端收到了后端生成的token,那么在之后的所有请求当前,都必须携带token.作为服务器来说,得验证这个token,是否合法. 一、验证token是否合法 1.1 OncePerRequestFilter过滤器 OncePerRequestFilter是 Spring 框架中的一个过滤器&#xff0c;用于确保在…

基于nodejs+vue的校园二手物品交易系统

作者&#xff1a;计算机学姐 开发技术&#xff1a;SpringBoot、SSM、Vue、MySQL、JSP、ElementUI、Python、小程序等&#xff0c;“文末源码”。 专栏推荐&#xff1a;前后端分离项目源码、SpringBoot项目源码、Vue项目源码、SSM项目源码 精品专栏&#xff1a;Java精选实战项目…

Rust 语言开发 ESP32C3 并在 Wokwi 电子模拟器上运行(esp-hal 非标准库、LCD1602、I2C)

文章目录 esp-rs 简介GithubRust 包仓库Wokwi 电子模拟器开发环境Rust 环境esp-rs 环境创建 ESP32C3 项目项目结构编译项目命令运行模拟器ESP32C3 烧录 esp-rs 简介 esp-rs 是一个专注于为 Espressif 系列芯片&#xff08;如 ESP32、ESP32-S2、ESP32-C3 等&#xff09;提供 Ru…

如何在 Three.js 场景中创建可点击展开的标签

在复杂的可视化场景中&#xff0c;经常需要为 3D 对象添加可交互的标签&#xff0c;以便用户点击时可以查看详细信息。这篇文章将通过一个简单的案例展示&#xff0c;如何在 Three.js 中为对象创建可点击的标签&#xff0c;点击标签可以展开详细信息&#xff0c;再次点击可以关…

论文复现:考虑电网交互的风电、光伏与电池互补调度运行(MATLAB-Yalmip-Cplex全代码)

论文复现:考虑电网交互的风电、光伏与电池储能互补调度运行(MATLAB-Yalmip-Cplex全代码) 针对风电、光伏与电化学储能电站互补运行的问题,已有大量通过启发式算法寻优的案例,但工程上更注重实用性和普适性。Yalmip工具箱则是一种基于MATLAB平台的优化软件工具箱,被广泛应用…