首页 > 解决方案 > 如何将 NA 值替换为赋予相同 ID 的先前非 NA 值

问题描述

我在 R 中工作并且正在使用 data.table。我有一个如下所示的数据集:

ID   country_id    weight
1    BGD           56
1    NA            57
1    NA            63
2    SA            12
2    NA            53
2    SA            54

如果 country_id 中的值为 NA 我需要将其替换为赋予相同 ID 的 non-na country_id 值。我希望数据集看起来像这样:

ID   country_id    weight
1    BGD           56
1    BGD           57
1    BGD           63
2    SA            12
2    SA            53
2    SA            54

该数据集包含数百万个 ID,因此无法手动修复每个 ID。

谢谢你的帮助!

编辑:解决了!

我使用了这个代码:dt[, country_id := country_id[!is.na(country_id)][1], by = ID]

标签: rdata.table

解决方案


另一种选择是使用连接:

DT[is.na(country_id), country_id := 
    DT[!is.na(country_id)][.SD, on=.(ID), mult="first", country_id]]

解释:

  1. DT[is.na(country_id)将数据集子集到 country_id 列中具有 NA 的数据集

  2. .SD是上一步中的数据子集(也是 data.table)。

  3. DT[!is.na(country_id)][.SD, on=.(ID)左连接使用.SD作为键。DT[!is.na(country_id)]ID

  4. j=country_id从右表返回 country_id 列DT[!is.na(country_id)],如果有多个匹配项,则mult="first"返回第一个匹配项。

  5. country_id :=country_id将DT 行中为 TRUE的列更新为is.na(country_id)连接的结果。

根据 Andrew 的时序代码和类似但更大的数据:

library(data.table)
set.seed(42)

nr <- 1e7
dt <- data.table(ID = rep(1:(nr/4), each = 4),
    country_id = rep(rep(c("BGD", "SA", "USA", "DEN", "THI"), each = 4)),
    weight = sample(10:100, nr, TRUE))
dt[sample(1:nr, nr/2), country_id := NA]
DT <- copy(dt)

microbenchmark::microbenchmark(
    first_nonmissing = dt[, country_id := country_id[!is.na(country_id)][1L], by = ID],
    use_join=DT[is.na(country_id), country_id := DT[!is.na(country_id)][.SD, on=.(ID), mult="first", country_id]],
    times = 1L
)

时间:

Unit: milliseconds
             expr       min        lq      mean    median        uq       max neval
 first_nonmissing 3282.1373 3282.1373 3282.1373 3282.1373 3282.1373 3282.1373     1
         use_join  554.5314  554.5314  554.5314  554.5314  554.5314  554.5314     1

推荐阅读