2012-11-09 46 views
2

我有以下代碼上/更新:部分替換的數據幀

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 

我想從partial_key匹配在V1列,其與相應的值替換在dfV2值。不匹配應保持原樣。

對於完整的密鑰,我會使用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 

回答

4

使用%in%是不必要的,因爲的match輸出已經包含了這些信息。所以,你可以做這樣的事情:

replacement <- partial_key$V2[match(df$V1, partial_key$V1)] 
df$V2 <- ifelse(is.na(replacement), df$V2, replacement) 

有時候,我希望[R具有類似於Excel的IFERROR基地if.na功能。我有它在我的Rprofile:

if.na <- function(value, value.if.na) ifelse(is.na(value), value.if.na, value) 
df$V2 <- if.na(replacement, df$V2) 
1

您可以合併,然後執行所需的rearrnagements

> 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 
1

另一種解決方案:

comb <- rbind(df, partial_key) 
df$V2 <- head(ave(comb$V2, comb$V1, 
        FUN = function(x) tail(x, 1)), -nrow(partial_key))