我有以下代码:
set.seed(47)
df <- data.frame(V1 = sample(letters[1:5], size = 10, replace = TRUE),
V2 = 101:110)
partial_key <- data.frame(V1 = letters[1:3], V2 = 1:3)
> df
V1 V2
1 e 101
2 b 102
3 d 103
4 e 104
5 c 105
6 d 106
7 b 107
8 c 108
9 c 109
10 e 110
> partial_key
V1 V2
1 a 1
2 b 2
3 c 3
我想将V2
中df
的值替换为partial_key
列中匹配的V1
的相应值。不匹配应保持原样。
使用完整的密钥,我会使用match
替换正确的值,但会将不匹配替换为NA
。
df[, "V2"] <- partial_key[match(df$V1, partial_key$V1), "V2"]
## Replaces too much
我可以与%in%
一起破解解决方案,但有更好的方法吗?更直观,更少打字?
df[df$V1 %in% partial_key$V1, "V2"] <-
partial_key[match(df$V1[df$V1 %in% partial_key$V1], partial_key$V1), "V2"]
## Works, but is there a better way?
> df
V1 V2
1 e 101
2 b 2
3 d 103
4 e 104
5 c 3
6 d 106
7 b 2
8 c 3
9 c 3
10 e 110
答案 0 :(得分:4)
由于%in%
的输出已包含该信息,因此无需使用match
。所以你可以这样做:
replacement <- partial_key$V2[match(df$V1, partial_key$V1)]
df$V2 <- ifelse(is.na(replacement), df$V2, replacement)
有时我希望R有一个类似于Excel if.na
的基本IFERROR
函数。我在我的Rprofile中有它:
if.na <- function(value, value.if.na) ifelse(is.na(value), value.if.na, value)
df$V2 <- if.na(replacement, df$V2)
答案 1 :(得分:1)
您可以合并然后执行所需的后方
> mdf <- merge(df, partial_key, by="V1", all.x=TRUE)
> mdf$V2.x[!is.na(mdf$V2.y)] <- mdf$V2.y[!is.na(mdf$V2.y)]
> mdf
V1 V2.x V2.y
1 b 2 2
2 b 2 2
3 c 3 3
4 c 3 3
5 c 3 3
6 d 106 NA
7 d 103 NA
8 e 101 NA
9 e 104 NA
10 e 110 NA
> mdf[-3]
V1 V2.x
1 b 2
2 b 2
3 c 3
4 c 3
5 c 3
6 d 106
7 d 103
8 e 101
9 e 104
10 e 110
答案 2 :(得分:1)
另一种解决方案:
comb <- rbind(df, partial_key)
df$V2 <- head(ave(comb$V2, comb$V1,
FUN = function(x) tail(x, 1)), -nrow(partial_key))