首页 > 解决方案 > 如何将 Pandas 数据帧拆分为从 NaN 到 NaN 的块?

问题描述

假设我有以下数据:

import pandas as pd

csv = [
    ['2019-05-01 00:00', ],
    ['2019-05-01 01:00', 2],
    ['2019-05-01 02:00', 4],
    ['2019-05-01 03:00', ],
    ['2019-05-01 04:00', 2],
    ['2019-05-01 05:00', 4],
    ['2019-05-01 06:00', 6],
    ['2019-05-01 07:00', ],
    ['2019-05-01 08:00', ],
    ['2019-05-01 09:00', 2]]

df = pd.DataFrame(csv, columns=["DateTime", "Value"])

所以我正在处理一个有数据空白的时间序列:

           DateTime  Value
0  2019-05-01 00:00    NaN
1  2019-05-01 01:00    2.0
2  2019-05-01 02:00    4.0
3  2019-05-01 03:00    NaN
4  2019-05-01 04:00    2.0
5  2019-05-01 05:00    4.0
6  2019-05-01 06:00    6.0
7  2019-05-01 07:00    NaN
8  2019-05-01 08:00    NaN
9  2019-05-01 09:00    2.0

现在,我想对现有数据的每一块逐个进行处理。我的意思是,我想将系列拆分为 NaN 之间的紧凑部分。目标是迭代这些块,以便我可以将每个块单独传递给另一个无法处理数据间隙的函数。然后,我想将结果存储在原始数据框中的相应位置。举个简单的例子,假设函数计算块的平均值。预期结果:

           DateTime  Value  ChunkAverage
0  2019-05-01 00:00    NaN           NaN
1  2019-05-01 01:00    2.0           3.0
2  2019-05-01 02:00    4.0           3.0
3  2019-05-01 03:00    NaN           NaN
4  2019-05-01 04:00    2.0           4.0
5  2019-05-01 05:00    4.0           4.0
6  2019-05-01 06:00    6.0           4.0
7  2019-05-01 07:00    NaN           NaN
8  2019-05-01 08:00    NaN           NaN
9  2019-05-01 09:00    2.0           2.0

我知道这可以通过迭代循环、“if”子句、索引切片等“传统方式”来实现。但我想 Pandas 中内置了一些更有效和安全的东西。但我不知道怎么做。

标签: pythonpandas

解决方案


您可以使用df.groupby, with 使用pd.Series.isnawithpd.Series.cumsum

g = df.Value.isna().cumsum()
df.assign(chunk = df.Value.groupby(g).transform('mean').mask(df.Value.isna()))
# df['chunk'] = df.Value.groupby(g).transform('mean').mask(df.Value.isna()))
# df['chunk'] = df.Value.groupby(g).transform('mean').where(df.Value.notna())

           DateTime  Value  chunk
0  2019-05-01 00:00    NaN    NaN
1  2019-05-01 01:00    2.0    3.0
2  2019-05-01 02:00    4.0    3.0
3  2019-05-01 03:00    NaN    NaN
4  2019-05-01 04:00    2.0    4.0
5  2019-05-01 05:00    4.0    4.0
6  2019-05-01 06:00    6.0    4.0
7  2019-05-01 07:00    NaN    NaN
8  2019-05-01 08:00    NaN    NaN
9  2019-05-01 09:00    2.0    2.0

笔记:

  • df.assign(...)给出新的数据框。
  • df['chunk'] = ...就地改变原始数据框

推荐阅读