假设我有一个数据框d1
,如下所示:
site code trait
1 1 A 1.0
2 2 B 1.3
3 3 A NA
4 4 B 2.9
5 5 A NA
以下是生成d1
的输入:
structure(list(site = 1:5, code = structure(c(1L, 2L, 1L, 2L,
1L), .Label = c("A", "B"), class = "factor"), trait = c(1, 1.3,
NA, 2.9, NA)), .Names = c("site", "code", "trait"), row.names = c(NA,
-5L), class = "data.frame")
我有第二个数据框d2
,如下所示:
code trait
1 A 1.5
2 B 2.5
以下是生成d2
的输入:
structure(list(code = structure(1:2, .Label = c("A", "B"), class = "factor"),
trait = c(1.5, 2.5)), .Names = c("code", "trait"), row.names = c(NA,
-2L), class = "data.frame")
我想要一段代码替换trait
的NA值,其中d2
的特征值与code
中特定行的d1
字符相匹配。 d1
的最终输出如下所示:
site code trait
1 1 A 1.0
2 2 B 1.3
3 3 A 1.5
4 4 B 2.9
5 5 A 1.5
我尝试的事情:
d1$trait<- ifelse(is.na(d1$trait),d2$trait[d2$code == d1$code],d1$trait)
使用此代码时,我收到警告:
警告信息:1:在is.na(e1)|中is.na(e2):较长的物体长度 不是较短对象长度2的倍数:在==。默认值(d2 $ code, d1 $ code):较长的对象长度不是较短对象的倍数 长度
答案 0 :(得分:3)
您的ifelse
语法很接近,但问题是:
d2$trait[d2$code == d1$code]
在这里,您尝试查找与d2$trait
中正确的code
值对应的d1
值,但实际上您只是在比较d2$code
的相应元素到d1$code
。可以使用match
:
d1$trait<- ifelse(is.na(d1$trait),d2$trait[match(d1$code, d2$code)], d1$trait)
d1
# site code trait
# 1 1 A 1.0
# 2 2 B 1.3
# 3 3 A 1.5
# 4 4 B 2.9
# 5 5 A 1.5
另一种方法是只替换缺失的值,再次使用match
来抓取d2$trait
中的相关元素:
d1$trait[is.na(d1$trait)] <- d2$trait[match(d1$code[is.na(d1$trait)], d2$code)]
d1
# site code trait
# 1 1 A 1.0
# 2 2 B 1.3
# 3 3 A 1.5
# 4 4 B 2.9
# 5 5 A 1.5
虽然match
和merge
在内部执行非常相似的操作,但我发现match
语法更容易使用,因为您不需要创建中间体通过merge
对象,然后从该中间对象中获取相关信息。
答案 1 :(得分:2)
这是一个简单的合并任务:
df12 <- merge(df1, df2, by="code", all.x=TRUE)
df12$trait <- ifelse(is.na(df12$trait.x), df12$trait.y, df12$trait.x)
答案 2 :(得分:1)
您也可以在没有使用dplyr
之类管道的中间对象的情况下完成此操作:
library(dplyr)
full_join(df1, df2, by="code") %>%
mutate(trait=ifelse(is.na(trait.x), trait.y, trait.x)) %>%
select(site, code, trait)
这里的优点是您不需要中间对象期间,并且您已准备好开始使用管道中的数据。