【问题标题】:merge values of duplicated indices, where NaN and then keep first合并重复索引的值,其中 NaN 然后先保留
【发布时间】:2021-01-30 07:55:09
【问题描述】:

假设有一个大的 Timeindex-DataFrame a,时间索引中有一些重复项。

其中一些重复的时间索引可能包含 NaN,其中第二个/第三个/...重复项确实有一个值。

如何将值“向上推”到上面的NaNs(以便它们被填充),然后删除除第一个之外的所有重复项? (这种向后填充应该只发生在相同日期时间的行之间,例如12.06.2019 00:00:05

使用pandasnumpy 的适当/有效方法是什么?

Time                       A            B          C        D
12.06.2019 00:00:00   1.1412          NaN    1.21412  1.21412  
12.06.2019 00:00:01   1.1464      1.12643    1.21412  1.21412
12.06.2019 00:00:02      NaN      1.12634        NaN  1.21445
12.06.2019 00:00:02   1.1453          NaN    1.21423      NaN
12.06.2019 00:00:03   1.1536      1.12589    1.21445  2. 2452
12.06.2019 00:00:04   1.1612      1.12978    1.21445  4.12451
12.06.2019 00:00:05   1.1275          NaN        NaN      NaN
12.06.2019 00:00:05      NaN      1.12978    1.21445      NaN
12.06.2019 00:00:06   1.1612      1.12978    1.21445  4.12451
a = pd.DataFrame({'A':[1.1412,1.1464,np.nan,1.1453,1.1536,1.1612,1.1275,np.nan,1.1612],  'B':[np.nan, 1.12643,1.12634,np.nan,1.12589,1.12978,np.nan,1.12978,1.12978],   'C':[1.21412,1.21412,np.nan,1.21423,1.21445,1.21445,np.nan,1.21445,1.21445],   'D':[1.21412,1.21412,1.21445,np.nan,2. 2452,4.12451,np.nan, np.nan, 4.12451]}, indexpd.DatetimeIndex=["12.06.2019 00:00:00","12.06.2019 00:00:01","12.06.2019 00:00:02","12.06.2019 00:00:02","12.06.2019 00:00:03","12.06.2019 00:00:04","12.06.2019 00:00:05","12.06.2019 00:00:05","12.06.2019 00:00:06"])

预期结果:

Time                       A            B          C        D
12.06.2019 00:00:00   1.1412          NaN    1.21412  1.21412  
12.06.2019 00:00:01   1.1464      1.12643    1.21412  1.21412
12.06.2019 00:00:02   1.1453      1.12634    1.21423  1.21445 
12.06.2019 00:00:03   1.1536      1.12589    1.21445  2. 2452
12.06.2019 00:00:04   1.1612      1.12978    1.21445  4.12451
12.06.2019 00:00:05   1.1275      1.12978    1.21445      NaN 
12.06.2019 00:00:06   1.1612      1.12978    1.21445  4.12451

【问题讨论】:

  • 嗨,有趣,也许过滤掉空值?
  • @IronMan 你能澄清一下过滤的方式吗?

标签: pandas numpy interpolation nan data-cleaning


【解决方案1】:

加载模块和数据:

import pandas as pd
import io

df = pd.read_csv(io.StringIO("""
Time                       A            B          C        D
12.06.2019 00:00:00   1.1412          NaN    1.21412  1.21412  
12.06.2019 00:00:01   1.1464      1.12643    1.21412  1.21412
12.06.2019 00:00:02      NaN      1.12634        NaN  1.21445
12.06.2019 00:00:02   1.1453          NaN    1.21423      NaN
12.06.2019 00:00:03   1.1536      1.12589    1.21445  2.2452
12.06.2019 00:00:04   1.1612      1.12978    1.21445  4.12451
12.06.2019 00:00:05   1.1275          NaN        NaN      NaN
12.06.2019 00:00:05      NaN      1.12978    1.21445      NaN
12.06.2019 00:00:06   1.1612      1.12978    1.21445  4.12451
"""), sep="\s\s+", engine="python")

用零填充缺失值:

ndf = df.fillna(0)

使用sum 执行groupby,它有效地将零替换为以前的值。 注意:如果两行在同一列下都有值,则此方法不起作用。

ndf.groupby('Time').agg({'A':sum, 'B':sum, 'C': sum, 'D': sum}) 

最后一步,零值可以恢复为np.nan

更新:如果没有 NAN,则取第一个值

首先,在同一日期下没有 NAN 的地方创建新数据。对于 12.06.2019 00:00:02,我将 A 列下的 NAN 替换为 1.5,将 B 列下的 NAN 替换为 3.0。

df = pd.read_csv(io.StringIO("""
Time                       A            B          C        D
12.06.2019 00:00:00   1.1412          NaN    1.21412  1.21412  
12.06.2019 00:00:01   1.1464      1.12643    1.21412  1.21412
12.06.2019 00:00:02      1.5      1.12634        NaN  1.21445
12.06.2019 00:00:02   1.1453          3.0    1.21423      NaN
12.06.2019 00:00:03   1.1536      1.12589    1.21445  2.2452
12.06.2019 00:00:04   1.1612      1.12978    1.21445  4.12451
12.06.2019 00:00:05   1.1275          NaN        NaN      NaN
12.06.2019 00:00:05      NaN      1.12978    1.21445      NaN
12.06.2019 00:00:06   1.1612      1.12978    1.21445  4.12451
"""), sep="\s\s+", engine="python")

使用以前的解决方案会导致错误,因为它会在任何地方对值求和。

首先,像以前一样,我们用零填充 NAN。

ndf = df.fillna(0)

以下函数(我们将在groupby 命令中使用)检查是否有零。如果有,则取 groupby 类别中数据的总和。如果不是,则取第一个出现的值。

def calcfunction(x):
    if any(x == 0 for x in x):
        return(sum(x))
    else:
        return(x.iloc[0])

以下groupby 的输出在 A 和 B 列中显示日期 12.06.2019 00:00:02 仅采用第一个值,而对于 C 和 D 列,有 NAN 被替换为零和与其他现有值相加。

ndf.groupby('Time').agg({'A':calcfunction, 'B':calcfunction, 'C': calcfunction, 'D': calcfunction})

【讨论】:

  • 如果数据集中已经有0s 怎么办?另外:您能否澄清一下“ f 两行在同一列下都有值”是什么意思? -> 因为如果有一列已经填充了第一个重复行,则不需要用后面的值填充它(但是:如果在此索引的其他列中存在 NaN,则应该填充它们)
  • 这很好。在这种情况下,我会先用 999 临时替换零,这样它们就不能被第二行中的值替换,然后全部设置回零。我的意思是,如果例如在 A 列中的 12.06.2019 00:00:02 没有 NAN 但所有值,我的解决方案就有问题;在这种情况下,我的代码会对这些值进行求和。让我考虑一下,我明天会回来。
  • 有没有办法(快速)找到一个保证不在列中的数字,而无需在大范围内迭代(因为这会花费大量时间和 RAM 内存)?
  • @HR_quantile:您可以通过(df['A'] == 1.1412).sum() 执行此操作,您可以将 1.1412 替换为您想要查找的任何值。请找到我添加的新解决方案。
猜你喜欢
  • 2012-11-14
  • 1970-01-01
  • 2012-08-25
  • 1970-01-01
  • 2014-09-04
  • 2022-01-22
  • 2013-09-08
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多