我的数据框df1
包含一个名为lepsp
和ID
的因子,另一个数据框df2
包含一个名为lepsp_updates
和{{1}的因子}}。我需要使用matchID
中的lepsp
更新df1中的所有lepsp_updates
信息。
这需要覆盖/替换一些当前df2
级别或填写该列的空白条目。但是,目前lepsp
对于许多条目都有lepsp_updates
,我不希望NA替换NA
的当前条目。这是当前的数据框:
lepsp
输出如下:
df1<- data.frame(ID= seq(1,10, 1),
lepsp= c("A", "B", "", "C", "B", "","", "A", "B" , "C"))
df2<- data.frame(matchID= c("2","3", "8"),
lepsp_updates= c("C", "E", "B"))
ID 2 B的通知被C替换,ID3 E替换了空白条目。 df1的所有其他原始条目保持不变。
我尝试过以下版本:
output<- data.frame(ID= seq(1,10, 1),
lepsp= c("A", "C", "E", "C", "B", "","", "B", "B" , "C"))
或使用更新向df1添加列,然后合并列。
df1$lepsp<- df2$lepsp_updated[match(df1$ID, df2$matchID)]
但是要么将因素更改为数字,要么覆盖数据,并且只保留来自一个因子级别的数据。
答案 0 :(得分:1)
这是你正在寻找的吗?
library(tidyverse)
df1 <- data.frame(ID = seq(1, 10, 1),
lepsp = c("A", "B", "", "C", "B", "", "", "A", "B" , "C"),
stringsAsFactors = FALSE)
df2 <- data.frame(matchID = c("2", "3", "8"),
lepsp_updates = c("C", "E", "B"),
stringsAsFactors = FALSE)
df2$matchID <- as.numeric(df2$matchID)
left_join(df1, df2, by = c("ID" = "matchID")) %>%
mutate(lepsp = if_else(is.na(lepsp_updates), lepsp, lepsp_updates)) %>%
select(ID, lepsp)
返回:
# ID lepsp
# 1 1 A
# 2 2 C
# 3 3 E
# 4 4 C
# 5 5 B
# 6 6
# 7 7
# 8 8 B
# 9 9 B
# 10 10 C
请注意,您必须在stringsAsFactors = FALSE
中加入data.frame
参数,如果您希望此解决方案有效,您还需要将matchID
转换为数字。
此外,将空白字符转换为NA
可能是个好主意。您可以通过向链中添加额外的mutate
来执行此操作:
left_join(df1, df2, by = c("ID" = "matchID")) %>%
mutate(lepsp = if_else(is.na(lepsp_updates), lepsp, lepsp_updates)) %>%
select(ID, lepsp) %>%
mutate_all(funs(replace(., . == '', NA)))
# ID lepsp
# 1 1 A
# 2 2 C
# 3 3 E
# 4 4 C
# 5 5 B
# 6 6 <NA>
# 7 7 <NA>
# 8 8 B
# 9 9 B
# 10 10 C
或者,您可以使用基数R将空白字符转换为NA
:
df <- left_join(df1, df2, by = c("ID" = "matchID")) %>%
mutate(lepsp = if_else(is.na(lepsp_updates), lepsp, lepsp_updates)) %>%
select(ID, lepsp)
df[df == ""] = NA