【问题标题】:Replace levels of factor with levels of another factor用另一个因子的水平替换因子的水平
【发布时间】:2017-11-26 05:46:45
【问题描述】:

我有一个数据框df1,其中有一个名为lepspID 的因子,还有一个带有lepsp_updatesmatchID 的因子的第二个数据框df2。我需要用df2 中的lepsp_updates 更新df1 中的所有lepsp 信息。

这将需要覆盖/替换一些当前的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"))  

输出如下所示:

 output<- data.frame(ID= seq(1,10, 1), 
               lepsp= c("A", "C", "E", "C", "B", "","", "B", "B" , "C"))

ID 2 B 的通知被替换为 C 并且 ID3 E 替换了空白条目。 df1 的所有其他原始条目保持不变。

我尝试过以下版本:

df1$lepsp<- df2$lepsp_updated[match(df1$ID, df2$matchID)]

或使用更新向 df1 添加一列,然后合并列。

df1 <- transform(df1, lepsp_updated = ifelse(is.na(lepsp_updated),lepsp, lepsp_updated))

但因子要么更改为数字,要么数据被覆盖,只保留一个因子级别的数据。

【问题讨论】:

    标签: r


    【解决方案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
    

    请注意,您必须在 data.frame 中包含 stringsAsFactors = FALSE 参数,如果您希望此解决方案起作用,还需要将 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
    

    或者,您可以将空白字符转换为NA,并使用基数 R:

    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
    

    【讨论】:

      猜你喜欢
      • 2015-04-04
      • 1970-01-01
      • 1970-01-01
      • 2020-11-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-12-07
      相关资源
      最近更新 更多