SFu*_*n28 14 indexing r dataframe
给定2个在列名/数据类型方面相同的数据帧,其中一些列唯一地标识行,是否有一个有效的函数/方法用于一个data.frame来"更新"另一个?
例如,在下文中,original并replacement通过识别'Name'和'Id'. goal为找到的所有行的结果replacement中original(由唯一的ID),并与替换Value1和Value2
original = data.frame( Name = c("joe","john") , Id = c( 1 , 2) , Value1 = c(1.2,NA), Value2 = c(NA,9.2) )
replacement = data.frame( Name = c("john") , Id = 2 , Value1 = 2.2 , value2 = 5.9)
goal = data.frame( Name = c("joe","john") , Id = c( 1 , 2) , Value1 = c(1.2,2.2), Value2 = c(NA,5.9) )
Run Code Online (Sandbox Code Playgroud)
该解决方案应为工作original和replacement任意长度的(尽管replacement不应该有超过行original).在实践中,我使用2个id列.
Ryo*_*ogi 11
我会用data.table对象.此代码似乎适用于您的示例:
library(data.table)
# set keys
original.dt <- data.table(original, key=c("Name", "Id"))
replacement.dt <- data.table(replacement, key=c("Name", "Id"))
goal2 <- original.dt
# subset and reassign
# goal2[replacement.dt[, list(Name, Id)]] <- replacement.dt
goal2[replacement.dt] <- replacement.dt # cleaner and faster, see Matthew's comment
goal2 <- as.data.frame(goal2)
identical(goal, goal2) # FALSE, why? See Joris's comment
all.equal(goal, goal2) # TRUE
Run Code Online (Sandbox Code Playgroud)
只需将唯一ID设置为行名称即可.然后它是简单的索引:
rownames(original) = original$Id
rownames(replacement) = replacement$Id
original[rownames(replacement), ] = replacement
Run Code Online (Sandbox Code Playgroud)
使用base R,您可以使用replace.df()下面的函数,该函数大致基于的源代码merge.data.frame()。与其他解决方案相反,此解决方案允许使用多个列进行标识。我在工作中经常使用它。随时复制和使用。
此函数控制在x中找不到y中的行的情况。请注意,该函数不会检查组合是否唯一。match()将仅用组合的首次出现替换第一次出现。
该函数的用法如下:
> replace.df(original, replacement,by=c('Name','Id'))
Name Id Value1 Value2
1 joe 1 1.2 NA
2 john 2 2.2 9.2
Run Code Online (Sandbox Code Playgroud)
请注意,这可以有效检测原始代码中的写入错误。replacement包含一个名为“ value2”(小v)的变量,而不是Value2(大写V)。纠正此问题后,结果将变为:
> replace.df(original, replacement,by=c('Name','Id'))
Name Id Value1 Value2
1 joe 1 1.2 NA
2 john 2 2.2 5.9
Run Code Online (Sandbox Code Playgroud)
您也可以使用该函数来仅更改某些列中的值
> replace.df(original, replacement,by=c('Name','Id'),cols='Value2')
Name Id Value1 Value2
1 joe 1 1.2 NA
2 john 2 NA 5.9
Run Code Online (Sandbox Code Playgroud)
功能:
replace.df <- function(x,y,by,cols=NULL
){
nx <- nrow(x)
ny <- nrow(y)
bx <- x[,by,drop=FALSE]
by <- y[,by,drop=FALSE]
bz <- do.call("paste", c(rbind(bx, by), sep = "\r"))
bx <- bz[seq_len(nx)]
by <- bz[nx + seq_len(ny)]
idx <- match(by,bx)
idy <- match(bx,by)
idy <- idy[!is.na(idy)]
if(is.null(cols)) {
cols <- intersect(names(x),names(y))
cols <- cols[!cols %in% by]
}
x[idx,cols] <- y[idy,cols]
x
}
Run Code Online (Sandbox Code Playgroud)