根据多个条件将数据框中的 NA 替换为第二个数据框中的值

Replace NAs in dataframe with values from second dataframe based on multiple criteria

我有两个 data.frames,每个都有数千行和几十列,它们都是通过合并几个 csv 文件创建的。 data.frames 正是我想要的。我还要补充一点,df1 和 df2 有几个共同的列。唯一的问题是,在其中一个,比如说 df1 中,对于某些列,有一些 NA(这是 expected/normal)。好消息是我有 NA 的相同列也出现在第二个 data.frame 中,比如 df2,但没有 NA。我想做的是用 df1 同一列中的值填充 df2 给定列中的 NA,其中每个值是根据 df1 和 df2 之间其他列值的匹配来选择的。

使用一些随机数据:

A<- format(seq(as.Date("2021/09/01"), by = "day", length.out = 26), format="%Y%m%d")
B<- format(seq(as.POSIXct("2021-1-1 15:00"), as.POSIXct("2021-1-02 16:00"), by = "hour"), format = "%H:%M")
C<- sample(1:100, 26, replace=FALSE)
D<- LETTERS
E<- paste(D, C)

df1<- cbind(A, B, C, D)
df2<- cbind(A, B, C, E)
df2[c(7:10, 13, 18:21), 3] <- NA #replace some of the values with NAs
df2<- df2[-c(2,5,11,17,23,26),] #delete some columns so df1 and df2 are of different size

我希望对于 df2$C,当找到 NA 值时,相应的 df2$A 和 df2$B 值都与所有 df1$A 和 df2$B 匹配。当且仅当在 df1 中找到匹配 df1$A 和 df1$B 的行时,df1$C 的对应值才会复制到 df2$C NA 值中。换句话说,对于上面的示例数据,如果 df2$C 中有一个 NA 值,则该特定行的日期和时间的相应组合应该与 df1 的所有日期和时间串联结果相匹配,当匹配时找到了,用df1$C对应的值替换df2$C中的NA。

# as an instance, a case of my df2 where a NA occurs is
df2[17,3] 

#This should be replaced with the value from
df1[21,3] 

# because the time and date of 
df2[17,] 

A          B          C          E 
"20210921"    "11:00"         NA     "U 46" 

#is the same than 
df1[21,] 

A          B          C          D 
"20210921"    "11:00"       "46"        "U" 

我 100% 确定每个 data.frame 中的 A 列和 B 列的串联在每个 data.frame 中给出唯一的结果,因此 df1$A 和 df1$B 的串联将是唯一的,同样适用于 df2。此外,可以肯定的是,df2$A 和 df2$B 的串联与 df1 中 A 列和 B 列的串联相匹配,将产生一个且唯一的值。出于这个原因,我尝试将每个 data.frames 列 A 和 B 连接到一个新列中,以在 Base R 的 elseif 循环中使用 match(paste(...,...)) 查找匹配值或者使用其他论坛中提出的 dplyr 库的其他解决方案,但我找不到适合我的解决方案。我认为这类似于具有多个条件的 Excel lookup/vlookup 函数,但我无法在 R.

中弄清楚这个函数

关于如何进行的任何建议?谢谢

既然你已经提到了 dplyr;它为工作提供了工具。只需在您希望匹配的列上 left_join,然后 coalesce 结果用第二个 table.

的匹配值替换 'C' 的缺失值
library(dplyr)
df1 <- as.data.frame(df1)
df2 <- as.data.frame(df2)

concatenate <- df2 %>%
    left_join(df1, by = c('A', 'B'), suffix = c('', '.y')) %>%
    mutate(C = coalesce(C, C.y)) %>%
    select(-c(C.y))

您可以创建唯一密钥来更新 df2

unique_key1 <- paste(df1$A, df1$B)
unique_key2 <- paste(df2$A, df2$B)
inds <- is.na(df2$C)
df2$C[inds] <- df1$C[match(unique_key2[inds], unique_key1)]
df2

#         A     B  C    E
#1  20210901 15:00 74 A 74
#2  20210903 17:00 27 C 27
#3  20210904 18:00 60 D 60
#4  20210906 20:00  7  F 7
#5  20210907 21:00 96 G 96
#6  20210908 22:00 98 H 98
#7  20210909 23:00 38 I 38
#8  20210910 00:00 89 J 89
#9  20210912 02:00 69 L 69
#10 20210913 03:00 72 M 72
#11 20210914 04:00 76 N 76
#12 20210915 05:00 63 O 63
#13 20210916 06:00 13 P 13
#14 20210918 08:00 25 R 25
#15 20210919 09:00 92 S 92
#16 20210920 10:00 21 T 21
#17 20210921 11:00 79 U 79
#18 20210922 12:00 41 V 41
#19 20210924 14:00 97 X 97
#20 20210925 15:00 16 Y 16

数据

cbind创建矩阵,使用data.frame创建数据帧。

df1 <- data.frame(A, B, C, D)
df2 <- data.frame(A, B, C, E)