我有两个数据框:
df1
x1 x2
1 a
2 b
3 c
4 d
Run Code Online (Sandbox Code Playgroud)
和
df2
x1 x2
2 zz
3 qq
Run Code Online (Sandbox Code Playgroud)
我想根据df1 $ x1和df2 $ x2之间的条件匹配,用df2 $ x2中的值替换df1 $ x2中的某些值,以产生:
df1
x1 x2
1 a
2 zz
3 qq
4 d
Run Code Online (Sandbox Code Playgroud)
Jor*_*eys 20
使用match(),假设df1中的值是唯一的.
df1 <- data.frame(x1=1:4,x2=letters[1:4],stringsAsFactors=FALSE)
df2 <- data.frame(x1=2:3,x2=c("zz","qq"),stringsAsFactors=FALSE)
df1$x2[match(df2$x1,df1$x1)] <- df2$x2
> df1
x1 x2
1 1 a
2 2 zz
3 3 qq
4 4 d
Run Code Online (Sandbox Code Playgroud)
如果值不是唯一的,请使用:
for(id in 1:nrow(df2)){
df1$x2[df1$x1 %in% df2$x1[id]] <- df2$x2[id]
}
Run Code Online (Sandbox Code Playgroud)
我看到 Joris 和 Aaron 都选择构建没有因素的示例。我当然可以理解这个选择。对于已经是因素的列的读者,也可以选择强制“字符”。有一个策略,避免了约束,这也允许的可能性,有可能是指数在df2未在df1其中,我相信会失效里斯Meys'但不是亚伦的解决方案发布至今:
df1 <- data.frame(x1=1:4,x2=letters[1:4])
df2 <- data.frame(x1=c(2,3,5), x2=c("zz", "qq", "xx") )
Run Code Online (Sandbox Code Playgroud)
它要求将级别扩展为包括两个因子变量的交集,然后还需要在 match(df1$x1, df2$x1) 中删除不匹配的列(= NA 值)
df1$x2 <- factor(df1$x2 , levels=c(levels(df1$x2), levels(df2$x2)) )
df1$x2[na.omit(match(df2$x1,df1$x1))] <- df2$x2[which(df2$x1 %in% df1$x1)]
df1
#-----------
x1 x2
1 1 a
2 2 zz
3 3 qq
4 4 d
Run Code Online (Sandbox Code Playgroud)
(请注意,R 的最新版本没有stringsAsFactors在data.frame函数默认值中设置为 TRUE,这与 R 的大部分历史不同。)
Joris的答案的第一部分是好的,但是在中的值不唯一的情况下df1,行式for循环在大型data.frames上无法很好地扩展。
您可以使用data.table“更新联接”来进行修改,这将非常快:
library(data.table)
setDT(df1); setDT(df2)
df1[df2, on = .(x1), x2 := i.x2]
Run Code Online (Sandbox Code Playgroud)
或者,假设您不关心维护行顺序,则可以使用SQL启发式的方法dplyr:
library(dplyr)
union_all(
inner_join( df1["x1"], df2 ), # x1 from df1 with matches in df2, x2 from df2
anti_join( df1, df2["x1"] ) # rows of df1 with no match in df2
) # %>% arrange(x1) # optional, won't maintain an arbitrary row order
Run Code Online (Sandbox Code Playgroud)
这些方法中的任何一个都将比逐行for循环更好地扩展。
我们可以使用eat我的包safejoin,并在列冲突时将匹配项从 rhs 中“修补”到 lhs 中。
# devtools::install_github("moodymudskipper/safejoin")
library(safejoin)
library(dplyr)
df1 <- data.frame(x1=1:4,x2=letters[1:4],stringsAsFactors=FALSE)
df2 <- data.frame(x1=2:3,x2=c("zz","qq"),stringsAsFactors=FALSE)
eat(df1, df2, .by = "x1", .conflict = "patch")
# x1 x2
# 1 1 a
# 2 2 zz
# 3 3 qq
# 4 4 d
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
20889 次 |
| 最近记录: |