【问题标题】:replace values in dataframe based on indexes on second dataframe R根据第二个数据帧 R 上的索引替换数据帧中的值
【发布时间】:2020-05-26 03:03:57
【问题描述】:

我有以下任务:用数据帧 B 中相同变量的值替换数据帧 A 中变量 V1 的值。接下来我模拟数据帧:

set.seed(123)

A<-data.frame(id1=sample(1:10,10),id2=sample(1:10,10),V1=rnorm(10),V2=rnorm(10))
###create dataframe B
B<-A[sample(1:10,5),1:3]
###change values to be updated in df A
B$V1<-rnorm(5)
###create a row which is not in A, to make it more interesting
B<-rbind(B,c(11,12,rnorm(1)))

现在我提供一个非最佳解决方案,我希望它更清洁

temp<-left_join(A,B,by=c("id1","id2"))
temp[!is.na(temp$V1.y),"V1.x"]<-temp[!is.na(temp$V1.y),"V1.y"]

A<-temp[,setdiff(colnames(temp),"V1.y")]
colnames(A)[colnames(A) %in% "V1.x"]<-"V1"

最好避免创建临时对象并直接修改 df A。此外,该解决方案应该是可扩展的,以替换 A 的多列中的值。我认为类似于

A[expression1,desired_cols]<-B[expression2,desired_cols]

其中expression1expression2 用于匹配df 中的索引,desired_cols 是要替换的列的名称

【问题讨论】:

    标签: r dataframe indexing replace


    【解决方案1】:

    我们可以使用来自data.table 的连接,并使用第二个数据集('B')的相应i. 列更新'A' 的列

    library(data.table)
    setDT(A)[B,  V1 := i.V1, on = .(id1, id2)]
    

    如果我们要替换多个列,请记下要替换的列

    nm1 <- names(A)[3:4]
    nm2 <- paste0("i.", nm1)
    setDT(A)[B, (nm1) := mget(nm2), on = .(id1, id2)]
    

    或者如果我们使用left_join,那么coalesce会更好

    library(dplyr)
    left_join(A, B, by = c('id1', 'id2')) %>%
            transmute(id1, id2, V1 = coalesce(V1.y, V1.x), V2)
    

    【讨论】:

    • 它可以扩展到多列替换??
    • @NicolasMolano 是的,你可以这样做setDT(A)[, B, names(A)[3:4] := mget(paste0("i.", names(A)[3:4])), on = .(id1, id2)]
    • 看来这个任务不能用 base R 用 A[expression1,desired_cols]
    • @NicolasMolano。可以通过base R 完成。也是。只需要。对您的代码进行简单的调整,即不要在 j 上选择单个列名,而是选择多个列
    猜你喜欢
    • 1970-01-01
    • 2012-08-13
    • 2022-07-21
    • 1970-01-01
    • 2020-06-22
    • 2016-04-29
    • 1970-01-01
    • 2022-01-26
    • 1970-01-01
    相关资源
    最近更新 更多