利用Pandas和NumPy高效筛选NaN附近有效数据的教程

利用Pandas和NumPy高效筛选NaN附近有效数据的教程

本教程探讨了在python中,如何高效地处理包含nan的数值数据,并为每个nan值智能地提取其前后指定数量的有效数值。文章将详细介绍如何结合使用pandas的ffill、numpy的sliding_window_view以及数据帧的join操作,以优雅且高效的方式实现这一复杂的数据筛选和选择逻辑,尤其适用于需要处理不规则数据缺失场景下的数据预处理任务。

在数据分析和预处理过程中,我们经常会遇到包含缺失值(NaN)的数值型数据。一个常见的需求是,当某个数据点为NaN时,我们需要从其周围提取固定数量的“有效”(非NaN)数值。这个任务的复杂性在于,有效数值可能不均匀分布在NaN点的前后,且提取过程中可能遇到其他的NaN值,需要灵活处理。传统的循环遍历方法效率低下,难以应对大规模数据集。本教程将介绍一种结合Pandas和NumPy的“巧妙”方法,以实现高效且灵活的NaN邻近有效数据筛选。

核心概念与工具

本解决方案主要依赖以下Pandas和NumPy的关键功能:

pandas.Series.ffill() (Forward Fill):向前填充缺失值。在此方案中,它被巧妙地用于将最近的有效数据点的索引向前传播,为后续的滑动窗口操作提供对齐依据。numpy.lib.stride_tricks.sliding_window_view():创建一个滑动窗口视图。它可以在不复制数据的情况下,高效地生成数组的滑动窗口视图,这对于提取连续的子序列非常有用。关键在于,我们将此操作应用于已过滤掉NaN的有效数据序列。pandas.DataFrame.join():根据索引合并两个DataFrame。我们将利用它将原始数据与通过滑动窗口生成的邻近有效数据合并。

实现步骤详解

假设我们有一个包含NaN值的Pandas DataFrame,目标是为每个NaN值提取其前B个和后A个有效数值。

1. 准备示例数据

首先,我们创建一个示例DataFrame,其中包含一些NaN值,以便演示。

import pandas as pdimport numpy as npfrom numpy.lib.stride_tricks import sliding_window_view as swv# 示例数据data = {    'col': [np.nan, 0.0, 1.0, 2.0, np.nan, np.nan, 3.0, 4.0, 5.0, np.nan, 6.0, np.nan, 7.0, 8.0, 9.0, np.nan, 10.0]}df = pd.DataFrame(data)print("原始数据:")print(df)

2. 定义提取参数并识别有效数据

我们定义需要提取的有效数值数量:B 为NaN之前的数量,A 为NaN之后的数量。然后,从DataFrame中提取目标列,并创建一个布尔掩码来识别非NaN值。

B = 2  # NaN前需要提取的有效数值数量A = 3  # NaN后需要提取的有效数值数量# 提取目标列为Series,并确保索引是范围索引s = df['col'].reset_index(drop=True)# 识别非NaN行m = s.notna()

3. 巧妙利用ffill对齐索引

这是解决方案中的一个关键步骤。我们首先将Series的索引转换为Series,然后使用where(m)将NaN值对应的索引替换为NaN,接着使用ffill()将这些NaN索引填充为它们前面最近的有效数值的原始索引。这个idx Series将成为我们后续对齐滑动窗口结果的桥梁。

# 掩盖NaN的索引,并用ffill向前填充,将NaN位置与最近的有效数值索引关联起来idx = s.index.to_series().where(m).ffill()

现在,idx Series中的每个元素(除了开头连续的NaN)都指向其自身或其前面最近的有效数值的原始索引。

4. 应用滑动窗口视图生成邻近数据

我们将sliding_window_view应用于只包含有效数值的Series (s[m])。这会生成一个多维数组,其中每一行都是一个滑动窗口。

# 在有效数值上应用滑动窗口视图# A+B 是窗口大小# 窗口的索引需要特殊处理,以与ffill后的idx对齐tmp = pd.DataFrame(swv(s[m], A + B),                    index=idx[m].shift(-B + 1)[:m.sum() - (A + B) + 1])

swv(s[m], A + B):在过滤掉NaN的Series s[m] 上创建大小为 A+B 的滑动窗口。index=idx[m].shift(-B + 1)[:m.sum() – (A + B) + 1]:这一步非常精巧。idx[m]:获取有效数值对应的 idx 值。.shift(-B + 1):将这些索引向后移动 B-1 个位置。这是为了将滑动窗口的起始点(即窗口中的第 B 个元素)与我们希望关联的NaN位置的 idx 值对齐。[:m.sum() – (A + B) + 1]:截取索引,使其长度与滑动窗口视图 swv(s[m], A + B) 生成的行数匹配。

5. 重构与合并结果

最后,我们将滑动窗口结果tmp重新索引到idx Series,然后将其索引设置为原始DataFrame的索引,并使用mask(m)操作来清除原始数据中非NaN行对应的邻近数据(因为我们只关心NaN位置的邻近数据),最终通过join操作合并回原始DataFrame。

# 重新索引tmp到ffill后的idx,设置回原始df的索引,并掩盖掉原始数据非NaN行对应的结果# 这样只有原始数据中为NaN的行,其新列才会有值out = df.join(tmp.reindex(idx).set_axis(df.index).mask(m))print("n处理结果:")print(out)

结果分析

运行上述代码,您将得到一个扩展的DataFrame:

原始数据:     col0    NaN1    0.02    1.03    2.04    NaN5    NaN6    3.07    4.08    5.09    NaN10   6.011   NaN12   7.013   8.014   9.015   NaN16  10.0处理结果:     col    0    1    2    3    40    NaN  NaN  NaN  NaN  NaN  NaN1    0.0  NaN  NaN  NaN  NaN  NaN2    1.0  NaN  NaN  NaN  NaN  NaN3    2.0  NaN  NaN  NaN  NaN  NaN4    NaN  1.0  2.0  3.0  4.0  5.05    NaN  1.0  2.0  3.0  4.0  5.06    3.0  NaN  NaN  NaN  NaN  NaN7    4.0  NaN  NaN  NaN  NaN  NaN8    5.0  NaN  NaN  NaN  NaN  NaN9    NaN  4.0  5.0  6.0  7.0  8.010   6.0  NaN  NaN  NaN  NaN  NaN11   NaN  5.0  6.0  7.0  8.0  9.012   7.0  NaN  NaN  NaN  NaN  NaN13   8.0  NaN  NaN  NaN  NaN  NaN14   9.0  NaN  NaN  NaN  NaN  NaN15   NaN  NaN  NaN  NaN  NaN  NaN16  10.0  NaN  NaN  NaN  NaN  NaN

观察输出结果:

原始数据列 col 保持不变。新增了以 0, 1, 2, 3, 4 为列名的新列。这些列代表了每个NaN位置(如果存在)提取到的 B+A 个有效邻近值。对于原始数据中为NaN的行(例如索引4、5、9、11),新的列中会显示其对应的有效邻近值。例如,索引4和5的NaN,其前面两个有效值是1.0, 2.0,后面三个有效值是3.0, 4.0, 5.0,所以新列显示 1.0, 2.0, 3.0, 4.0, 5.0。对于原始数据中非NaN的行,新增的列则为NaN,因为我们只关心填充NaN位置。对于末尾的NaN(索引15),由于其后没有足够的有效值,因此新的列也显示为NaN。这表明该方法能够自动处理边界条件。

注意事项与优化

参数 B 和 A 的含义: B 代表NaN“之前”所需的有效数值数量,A 代表NaN“之后”所需的有效数值数量。它们决定了滑动窗口的大小和提取的范围。性能: 此方法充分利用了NumPy的矢量化操作和 sliding_window_view 的视图特性(不复制数据),以及Pandas的优化内部实现,因此在大数据集上表现出优异的性能,远超基于Python循环的实现。灵活性: 通过简单地调整 B 和 A 的值,可以轻松改变提取邻近数据的策略。理解复杂性: 尽管代码相对简洁,但理解 idx 的生成逻辑、sliding_window_view 的索引对齐以及 mask(m) 的作用是掌握此方法的关键。它巧妙地将原始索引、有效数据索引和滑动窗口结果关联起来。边界条件处理: 当NaN位于数据序列的开头或结尾,或者其周围没有足够的有效数值时,sliding_window_view 的结果会相应减少,并且最终的 join 操作会正确地填充NaN,表示无法获取足够的邻近数据。

总结

本教程介绍了一种在Python中利用Pandas和NumPy高效处理NaN值并提取其邻近有效数据的专业方法。通过结合 pandas.Series.ffill()、numpy.lib.stride_tricks.sliding_window_view() 和 pandas.DataFrame.join(),我们能够以一种矢量化、高性能的方式解决这一常见的数据预处理挑战。这种方法不仅代码简洁,而且能够优雅地处理各种复杂的边界条件和NaN分布情况,是数据科学家和工程师在处理不规则缺失数据时的有力工具。

以上就是利用Pandas和NumPy高效筛选NaN附近有效数据的教程的详细内容,更多请关注创想鸟其它相关文章!

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 chuangxiangniao@163.com 举报,一经查实,本站将立刻删除。
发布者:程序猿,转转请注明出处:https://www.chuangxiangniao.com/p/1379021.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2025年12月14日 20:18:07
下一篇 2025年12月14日 20:18:20

相关推荐

  • 如何对多层索引DataFrame应用不同规则进行分组聚合

    本教程详细介绍了如何对Pandas多层索引DataFrame的不同层级应用不同的分组规则。当需要根据第一层索引进行常规分组,而根据第二层索引的自定义逻辑(如字符串截取)进行分组时,直接使用`groupby`函数可能难以实现。文章将展示一种高效策略:通过重置索引将层级转换为普通列,对目标列进行数据转换…

    2025年12月14日
    000
  • Python调用API接口如何分页获取数据_Python调用API接口实现分页查询数据的技巧

    答案:通过页码、偏移量或游标方式循环请求API分页数据,结合响应信息判断是否继续,并添加延迟与重试机制以确保稳定性。 如果您需要从API接口获取大量数据,但响应结果被限制为分页形式,则必须通过循环请求每一页来获取完整数据集。以下是实现分页查询的常用技巧和方法: 一、基于页码的分页获取 许多API使用…

    2025年12月14日
    000
  • Flask SQLAlchemy中防止数据重复插入的策略与实践

    本文旨在探讨在flask应用中使用sqlalchemy将列表数据插入数据库时,如何有效避免数据重复插入的问题。我们将深入分析导致重复的常见原因,并提供两种核心策略:一是利用数据库的唯一性约束进行数据校验与插入,二是采用web开发中的post-redirect-get模式来防止用户意外刷新导致的重复提…

    2025年12月14日
    000
  • GTK3 Python应用中高效管理动态CSS样式指南

    本教程深入探讨了在python gtk3应用中动态管理css样式的有效策略。针对传统单css提供器在运行时难以修改样式且不丢失原有定义的问题,文章提出了两种主要解决方案:一是利用多个css提供器并结合优先级机制实现样式覆盖,二是采用css类进行细粒度控制,通过动态添加和移除类来切换预定义样式。教程通…

    2025年12月14日
    000
  • 使用Python模拟API请求抓取Yahoo Finance历史财报数据

    本教程旨在解决使用python抓取yahoo finance动态加载财报数据的问题。由于yahoo finance的财报页面内容通过javascript动态加载,传统的beautifulsoup直接解析html的方法往往无法获取完整数据。我们将深入探讨如何通过模拟浏览器api请求,直接从yahoo …

    2025年12月14日
    000
  • Wagtail自定义设置的集成与故障排除指南

    本教程详细介绍了如何在wagtail cms中集成自定义设置,并将其注册到后台管理界面。文章将逐步指导您定义设置模型、使用`wagtail.contrib.settings`和`wagtail.contrib.modeladmin`进行注册,并特别指出一个常见陷阱:自定义`construct_set…

    2025年12月14日
    000
  • 解决树莓派4B上OpenCV cv2导入错误的教程

    本文旨在解决树莓派4b上导入`cv2`库时遇到的`importerror: undefined symbol: __atomic_store_8`问题。我们将提供两种解决方案:一种是使用`ld_preload`进行快速临时修复,另一种是涉及通过特定`cmake`标志重新编译opencv的永久性方法。…

    2025年12月14日
    000
  • Python猜谜游戏:优化条件逻辑以实现准确的用户反馈

    本教程深入探讨python猜谜游戏中常见的逻辑陷阱,即如何避免在用户输入正确答案时,程序仍错误地显示“答案错误”的提示。我们将分析原始代码中条件判断的误区,并提供一个经过优化的解决方案。通过精确调整条件语句的执行顺序和结构,确保只有在猜错时才给出错误反馈,从而提升程序的交互准确性和用户体验。 原始代…

    2025年12月14日
    000
  • Python爬虫怎么写_Python网络爬虫编写步骤与实战案例

    答案:编写Python爬虫需先分析网页结构,用requests发送请求获取HTML,再用BeautifulSoup解析提取数据,最后清洗并存储为CSV或数据库;以豆瓣电影Top250为例,通过设置headers、分页爬取、解析class标签获取电影名、评分等信息,保存为CSV文件,并注意遵守robo…

    2025年12月14日
    000
  • Python官网项目模板的获取使用_Python官网快速启动项目指南

    首先使用Python官网推荐的标准项目模板快速搭建结构,接着可通过pipx安装Cookiecutter、用Poetry初始化项目或克隆GitHub高质量样板库来高效启动开发,确保项目具备良好组织与可维护性。 如果您希望快速启动一个Python项目,但不清楚如何组织文件结构或配置基础设置,可以直接使用…

    2025年12月14日
    000
  • 优化大规模细胞突变模拟:使用Numba提升Python/NumPy性能

    本文探讨了在python中模拟大规模细胞突变时遇到的性能瓶颈,特别是在处理数亿个细胞的数组操作和随机数生成方面。针对numpy在处理此类任务时的效率问题,文章提出并详细阐述了如何利用numba进行即时编译和优化,包括高效的整数型随机数生成、减少内存访问以及启用并行计算。通过这些优化,模拟速度可显著提…

    2025年12月14日
    000
  • 持久化ChromaDB向量嵌入:避免重复计算的教程

    本教程详细介绍了如何使用chromadb的`persist_directory`功能来高效地保存和加载向量嵌入数据库,从而避免重复计算。通过指定一个持久化目录,用户可以轻松地将生成的嵌入结果存储到本地文件系统,并在后续操作中直接加载,极大地节省了时间和计算资源。文章提供了清晰的代码示例和关键注意事项…

    2025年12月14日
    000
  • 在Xcelium中为Specman设置环境变量的策略与注意事项

    在Xcelium仿真环境中为Specman设置环境变量以集成外部工具(如Python)是一个常见挑战。本文将深入探讨环境变量的作用域、设置方法及其在复杂仿真流程中的继承机制,提供通过Shell脚本、Xcelium启动参数以及Specman ‘e’ 代码进行设置的详细指导,并强…

    2025年12月14日
    000
  • Python特殊方法文档中的object.前缀解读:并非指代object基类

    python文档中对特殊方法(如`__len__`、`__getitem__`)使用`object.`前缀,并非指这些方法是`object`基类的属性,也不是要求将它们添加到`object`类。这是一种文档约定,旨在表明这些是用户定义的任意类可以实现的方法,以模拟内置类型行为,从而融入python的…

    2025年12月14日
    000
  • 解决Kaggle环境中DuckDuckGo API调用HTTP错误指南

    在使用kaggle jupyter notebook进行机器学习课程(如fast.ai)时,调用`duckduckgo_search`库进行图片搜索可能会遇到`httperror`。本文将深入分析此问题的原因,并提供一个简单而有效的解决方案:通过更新kaggle notebook的环境配置,确保使用…

    2025年12月14日
    000
  • Python中实现+=操作符的动态类型处理策略

    本文探讨在Python中创建变量,使其能够灵活地通过`+=`操作符处理字符串和整数等不同初始数据类型的方法。文章将介绍两种核心模式:`StringBuilder`模式,用于将所有操作统一为字符串拼接;以及`UniversalIdentity`模式,通过自定义运算符重载,使变量能够动态适配第一个操作数…

    2025年12月14日
    000
  • Python环境管理深度解析:理解pipx与虚拟环境的正确应用

    本文深入探讨python包管理工具pipx与传统虚拟环境(如venv)之间的关键差异和正确应用场景。我们将解释为何pipx安装的库无法直接导入到python脚本中,因为其设计宗旨是为命令行应用程序提供隔离环境。教程将指导用户如何利用虚拟环境正确安装和管理项目所需的python库,确保模块可导入性,并…

    2025年12月14日
    000
  • Python中(回车符)的行为解析与行内更新技巧

    本文深入探讨了Python中回车符`r`的工作原理,解释了为何在使用`r`进行行内更新时可能出现残余字符,如”Time’s up!ning: 1″。文章通过具体代码示例,详细分析了该现象产生的原因,并提供了两种解决方案:一是放弃行内更新,采用默认换行符`n`;二是…

    2025年12月14日
    000
  • 使用Python和Selenium抓取动态网页数据教程

    本教程旨在指导读者如何使用python结合selenium和beautifulsoup库,有效抓取包含切换按钮等动态交互元素的网页数据。文章将详细阐述传统静态网页抓取方法在处理此类场景时的局限性,并提供一套完整的解决方案,通过模拟用户浏览器行为来获取动态加载的内容,最终实现对目标数据的精确提取。 在…

    2025年12月14日
    000
  • Python3数据类型有哪些_Python3常见数据类型全面解析

    Python3基本数据类型包括数字、字符串、列表、元组、字典、集合和布尔类型。1、数字类型含int、float、complex,分别表示整数、浮点数和复数;2、字符串是不可变的字符序列,用单、双或三引号定义,支持索引与切片;3、列表为有序可变序列,用方括号定义,可进行增删改查操作;4、元组为有序不可…

    2025年12月14日
    000

发表回复

登录后才能评论
关注微信