将因子水平替换为另一因子的水平

时间:2017-11-25 20:43:14

标签: r

我的数据框df1包含一个名为lepspID的因子,另一个数据框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)]

但是要么将因素更改为数字,要么覆盖数据,并且只保留来自一个因子级别的数据。

1 个答案:

答案 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