【问题标题】:Replace missing values by merging with another row通过与另一行合并来替换缺失值
【发布时间】:2026-02-17 04:00:01
【问题描述】:

我将来自不同来源的数据读取到 data.table 中。两个源为同一时间步提供不同的变量。

如何用其他来源(行)替换缺失的变量?

   Here is a minimal example: 
   (gg = data.table(SourceCode = c(1,1,2,2), time = c(1,2,1,2), LE = c(10,10,NA,NA), R = c(NA,NA,20,30)))
   SourceCode time LE  R
1:          1    1 10 NA
2:          1    2 10 NA
3:          2    1 NA 20
4:          2    2 NA 30

> # rename SourceCode
> gg[SourceCode == 1, SourceCode := 2 ]
> gg
   SourceCode time LE  R
1:          2    1 10 NA
2:          2    2 10 NA
3:          2    1 NA 20
4:          2    2 NA 30

期望的输出:

   SourceCode time LE  R
1:          2    1 10 20
2:          2    2 10 30

【问题讨论】:

  • 请提供您已经尝试过的代码。目前您的帖子没有任何问题。

标签: r data.table


【解决方案1】:

我最近有a similar question,发现dplyr::coalesce()

简单的解决方案是:

library(dplyr)
coalesce(
  filter(gg, SourceCode == 2),
  filter(gg, SourceCode == 1)
)
  SourceCode time LE  R
1          2    1 10 20
2          2    2 10 30

但更通用:

do.call(coalesce, split(gg, gg$SourceCode))
   SourceCode time LE  R
1:          1    1 10 20
2:          1    2 10 30

如果您想以第二个来源(或最后一个来源)为基础,您可以这样做:

do.call(coalesce, rev(split(gg, gg$SourceCode)))
   SourceCode time LE  R
1:          2    1 10 20
2:          2    2 10 30

【讨论】:

    【解决方案2】:

    由于您似乎正在使用data.tables,因此这里有一个data.table 解决方案

    unique(gg[, `:=`(LE = LE[!is.na(LE)], R = R[!is.na(R)]), by = time], by = "time")
    #   SourceCode time LE  R
    #1:          1    1 10 20
    #2:          1    2 10 30
    

    或者对于第二个来源

    unique(gg[, `:=`(LE = LE[!is.na(LE)], R = R[!is.na(R)]), by = time], by = "time", fromLast = T)
    #   SourceCode time LE  R
    #1:          2    1 10 20
    #2:          2    2 10 30
    

    由于SourceCode 似乎不再相关(您总结不同的SourceCodes)您也可以这样做

    gg[, lapply(.SD, function(x) x[!is.na(x)]), by = time, .SDcols = 3:4]
    #   time LE  R
    #1:    1 10 20
    #2:    2 10 30
    

    【讨论】:

      【解决方案3】:

      一个选项:

      library(tidyverse)
      dd %>% 
          gather(var, val, -SourceCode, -time) %>% 
          na.omit(val) %>% 
          spread(var, val)
      
      #   SourceCode time LE  R
      # 1          2    1 10 20
      # 2          2    2 10 30
      

      或基于分组的另一个选项

      dd %>% 
          group_by(SourceCode, time) %>% 
          summarise_at(vars(LE:R), .funs = funs(.[which(!is.na(.))]))
      
      #   SourceCode time LE  R
      # 1          2    1 10 20
      # 2          2    2 10 30
      

      请注意,我只在 group_by 调用中添加 SourceCode 以将其保留在摘要中。如果您不需要该列,则可以省略它。

      【讨论】:

        最近更新 更多