我有两个数据框:
df1 <-data.frame(ID=c(1,2,3,4,5), date=c(NA,NA,NA,NA,NA), outcome=c(NA,1,NA,NA,0))
df1
ID date outcome
1 1 NA NA
2 2 NA 1
3 3 NA NA
4 4 NA NA
5 5 NA 0
df2 <-data.frame(ID=c(3,25,222,415,700), date=c(010215,032412,040513,041015,120314), outcome=c(1,1,1,1,1))
df2
ID date outcome
1 3 10215 1
2 25 32412 1
3 222 40513 1
4 415 41015 1
5 700 120314 1
如果df1中的ID在df2中,那么我想用df2 $ date替换df1 $ date。另外,如果df1中的ID在df2中,我想设置df1 $ outcome =1。我可以使用以下代码执行此操作:
df1$date <-ifelse(df1$ID %in% df2$ID, df2$date[match(df1$ID,df2$ID)],df1$date)
df1$outcome <-ifelse(df1$ID %in% df2$ID, 1,df1$outcome)
df1
ID date outcome
1 1 NA NA
2 2 NA 1
3 3 10215 1
4 4 NA NA
5 5 NA 0
但是我想了解如何使用一个if语句来做到这一点。我想出了以下代码:
for(i in 1:nrow(df1)){
if(df1$ID[i] %in% df2$ID){
df1$outcome[i]==1 & df1$date[i]==df2$date[match(df1$ID,df2$ID)]
}
}
df1
ID date outcome
1 1 NA NA
2 2 NA 1
3 3 NA NA
4 4 NA NA
5 5 NA 0
可以正常运行,但不能完成所需的替换。有人可以建议如何修改我所做的工作以使其像第一个代码块一样工作吗?
答案 0 :(得分:2)
如果要继续进行for
循环,一种方法是
for(i in 1:nrow(df1)){
if(df1$ID[i] %in% df2$ID) {
df1$date[i] = df2$date[match(df1$ID[i],df2$ID)]
df1$outcome[i] = 1
}
}
df1
# ID date outcome
#1 1 NA NA
#2 2 NA 1
#3 3 10215 1
#4 4 NA NA
#5 5 NA 0
但是,非for循环方式将使用match
,在该方法中,我们计算索引仅替换一次,并使用它来更改date
和outcome
的值。
inds <- match(df1$ID, df2$ID)
df1$date <- df2$date[inds]
df1$outcome[which(!is.na(inds))] <- 1
答案 1 :(得分:1)
您可以使用coalesce
包中的dplyr
:您完全不需要使用if-else
library(dplyr)
coalesce(df1, left_join(df1['ID'], df2, by = 'ID'))
ID date outcome
1 1 NA NA
2 2 NA 1
3 3 10215 1
4 4 NA NA
5 5 NA 0
答案 2 :(得分:0)
使用查找:
df1 <-data.frame(ID=c(1,2,3,4,5), date=c(NA,NA,NA,NA,NA), outcome=c(NA,1,NA,NA,0))
df2 <-data.frame(ID=c(3,25,222,415,700), date=c(010215,032412,040513,041015,120314), outcome=c(1,1,1,1,1))
col_vec <- c("date", "outcome")
df1[ , col_vec] <- lapply(col_vec,
function(x) {
mask <- is.na(df1[[x]])
result <- df1[[x]]
result[mask] <- setNames(df2[[x]], df2$ID)[as.character(df1$ID)[mask]]
result
})
df1
# ID date outcome
# 1 1 NA NA
# 2 2 NA 1
# 3 3 10215 1
# 4 4 NA NA
# 5 5 NA 0