0

0

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

碧海醫心

碧海醫心

发布时间:2025-11-10 12:16:01

|

325人浏览过

|

来源于php中文网

原创

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

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

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

核心概念与工具

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

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

实现步骤详解

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

1. 准备示例数据

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

import pandas as pd
import numpy as np
from 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)都指向其自身或其前面最近的有效数值的原始索引。

Motiff
Motiff

Motiff是由猿辅导旗下的一款界面设计工具,定位为“AI时代设计工具”

下载

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:

原始数据:
     col
0    NaN
1    0.0
2    1.0
3    2.0
4    NaN
5    NaN
6    3.0
7    4.0
8    5.0
9    NaN
10   6.0
11   NaN
12   7.0
13   8.0
14   9.0
15   NaN
16  10.0

处理结果:
     col    0    1    2    3    4
0    NaN  NaN  NaN  NaN  NaN  NaN
1    0.0  NaN  NaN  NaN  NaN  NaN
2    1.0  NaN  NaN  NaN  NaN  NaN
3    2.0  NaN  NaN  NaN  NaN  NaN
4    NaN  1.0  2.0  3.0  4.0  5.0
5    NaN  1.0  2.0  3.0  4.0  5.0
6    3.0  NaN  NaN  NaN  NaN  NaN
7    4.0  NaN  NaN  NaN  NaN  NaN
8    5.0  NaN  NaN  NaN  NaN  NaN
9    NaN  4.0  5.0  6.0  7.0  8.0
10   6.0  NaN  NaN  NaN  NaN  NaN
11   NaN  5.0  6.0  7.0  8.0  9.0
12   7.0  NaN  NaN  NaN  NaN  NaN
13   8.0  NaN  NaN  NaN  NaN  NaN
14   9.0  NaN  NaN  NaN  NaN  NaN
15   NaN  NaN  NaN  NaN  NaN  NaN
16  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分布情况,是数据科学家和工程师在处理不规则缺失数据时的有力工具。

相关专题

更多
python开发工具
python开发工具

php中文网为大家提供各种python开发工具,好的开发工具,可帮助开发者攻克编程学习中的基础障碍,理解每一行源代码在程序执行时在计算机中的过程。php中文网还为大家带来python相关课程以及相关文章等内容,供大家免费下载使用。

727

2023.06.15

python打包成可执行文件
python打包成可执行文件

本专题为大家带来python打包成可执行文件相关的文章,大家可以免费的下载体验。

630

2023.07.20

python能做什么
python能做什么

python能做的有:可用于开发基于控制台的应用程序、多媒体部分开发、用于开发基于Web的应用程序、使用python处理数据、系统编程等等。本专题为大家提供python相关的各种文章、以及下载和课程。

747

2023.07.25

format在python中的用法
format在python中的用法

Python中的format是一种字符串格式化方法,用于将变量或值插入到字符串中的占位符位置。通过format方法,我们可以动态地构建字符串,使其包含不同值。php中文网给大家带来了相关的教程以及文章,欢迎大家前来阅读学习。

617

2023.07.31

python教程
python教程

Python已成为一门网红语言,即使是在非编程开发者当中,也掀起了一股学习的热潮。本专题为大家带来python教程的相关文章,大家可以免费体验学习。

1236

2023.08.03

python环境变量的配置
python环境变量的配置

Python是一种流行的编程语言,被广泛用于软件开发、数据分析和科学计算等领域。在安装Python之后,我们需要配置环境变量,以便在任何位置都能够访问Python的可执行文件。php中文网给大家带来了相关的教程以及文章,欢迎大家前来学习阅读。

547

2023.08.04

python eval
python eval

eval函数是Python中一个非常强大的函数,它可以将字符串作为Python代码进行执行,实现动态编程的效果。然而,由于其潜在的安全风险和性能问题,需要谨慎使用。php中文网给大家带来了相关的教程以及文章,欢迎大家前来学习阅读。

575

2023.08.04

scratch和python区别
scratch和python区别

scratch和python的区别:1、scratch是一种专为初学者设计的图形化编程语言,python是一种文本编程语言;2、scratch使用的是基于积木的编程语法,python采用更加传统的文本编程语法等等。本专题为大家提供scratch和python相关的文章、下载、课程内容,供大家免费下载体验。

702

2023.08.11

php源码安装教程大全
php源码安装教程大全

本专题整合了php源码安装教程,阅读专题下面的文章了解更多详细内容。

177

2025.12.31

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
最新Python教程 从入门到精通
最新Python教程 从入门到精通

共4课时 | 0.6万人学习

Django 教程
Django 教程

共28课时 | 2.7万人学习

SciPy 教程
SciPy 教程

共10课时 | 1.0万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号