根据 id 将 NA 替换为其他行值

Replace NA with other row value based on id

我想用基于 ID 的其他行的值替换 NA。 我发现了类似的问题,但我没有找到解决问题的方法。

table以下部分

   XCODE Age Sex ResultA ResultB ResultC
1   X001  12   2       2       3       4
2   X002  23   2       4       6      66
3   X003  NA  NA      NA      NA      NA
4   X004  32   1       1       7       3
5   X005  NA  NA      NA      NA      NA
6   X001  NA  NA      NA      NA      NA
7   X002  NA  NA      NA      NA      NA
8   X003  33   1       8       7       6
9   X004  NA  NA      NA      NA      NA
10  X005  55   2       8       8       8

我有超过 6000 列的 SPSS 文件。

我用过

library(data.table)
setDT(dataset)[, Age:= Age[!is.na(Age)][1L] , by = XCODE]

但这只适用于单列,我需要处理很多列。

那么如何在所有列上执行上面的代码?

使用 data.table 我们可以 select 我们想要的列 replace

library(data.table)
setDT(df)[, (2:ncol(df)) := lapply(.SD, function(x) 
            replace(x, is.na(x), x[!is.na(x)][1])) , XCODE]

df
#    XCODE Age Sex ResultA ResultB ResultC
# 1:  X001  12   2       2       3       4
# 2:  X002  23   2       4       6      66
# 3:  X003  33   1       8       7       6
# 4:  X004  32   1       1       7       3
# 5:  X005  55   2       8       8       8
# 6:  X001  12   2       2       3       4
# 7:  X002  23   2       4       6      66
# 8:  X003  33   1       8       7       6
# 9:  X004  32   1       1       7       3
#10:  X005  55   2       8       8       8

使用 dplyr 中的相同逻辑,我们可以将 NAs 替换为所有列的组的第一个非 NA 值

library(dplyr)

df %>%
  group_by(XCODE) %>%
  mutate_all(~replace(., is.na(.), .[!is.na(.)][1]))


#  XCODE   Age   Sex ResultA ResultB ResultC
#   <fct> <int> <int>   <int>   <int>   <int>
# 1 X001     12     2       2       3       4
# 2 X002     23     2       4       6      66
# 3 X003     33     1       8       7       6
# 4 X004     32     1       1       7       3
# 5 X005     55     2       8       8       8
# 6 X001     12     2       2       3       4
# 7 X002     23     2       4       6      66
# 8 X003     33     1       8       7       6
# 9 X004     32     1       1       7       3
#10 X005     55     2       8       8       8

或仅select列

cols <- c("Age", "Sex", "ResultA","ResultB")
df %>%
  group_by(XCODE) %>%
  mutate_at(vars(cols), ~ replace(., is.na(.), .[!is.na(.)][1]))

我们可以按 XCODE 分组,并使用 fill() 将 NA 填入最新的非 NA。在这种情况下,我们需要填写两个方向。另请注意,由于您要填充所有变量,因此可以使用函数 everything()

library(tidyverse)

df %>% 
 group_by(XCODE) %>% 
 fill(everything()) %>% 
 fill(everything(), .direction = 'up')

这给出了,

# A tibble: 10 x 6
# Groups:   XCODE [5]
   XCODE   Age   Sex ResultA ResultB ResultC
   <fct> <int> <int>   <int>   <int>   <int>
 1 X001     12     2       2       3       4
 2 X001     12     2       2       3       4
 3 X002     23     2       4       6      66
 4 X002     23     2       4       6      66
 5 X003     33     1       8       7       6
 6 X003     33     1       8       7       6
 7 X004     32     1       1       7       3
 8 X004     32     1       1       7       3
 9 X005     55     2       8       8       8
10 X005     55     2       8       8       8