【问题标题】:Matching and replacing factor values using id使用 id 匹配和替换因子值
【发布时间】:2018-06-13 10:43:42
【问题描述】:

我有两个数据框,它们都包含相同的变量和每个观察的唯一 ID。

df.1 是一个大型数据集,其中包含由 NA 表示的缺失值。这些缺失条目的值包含在 df.2 中,我想通过匹配 id 将 df.1 中的缺失值替换为 df.2 中的值。

我在这里找不到类似的问题,考虑到它们都是因子变量。

为了简单起见:如果 id 匹配 - df.1 中的缺失值应替换为 df.2 中的因子值。

df.1 <- data.frame(id = c(334,440,501,2304,2500), 
                v1 = c("4 dogs",NA,"3 dogs",NA,"No dogs"))

df.2 <- data.frame(id = c(440,2304), 
                v2 = c("4 dogs","5 dogs"))

非常感谢您的帮助。

【问题讨论】:

  • 你检查了这些,我想这已经得到了回答。 herehere
  • 不幸的是,情况并非如此。我希望代码简单地匹配两个变量之间的 id 并将值从 df.2 替换为 df.1。 id 仅指定 df.1 中缺少的值。
  • 为什么需要将它们作为两个因子变量?只需转换为character
  • within(merge(df.1, df.2, all = TRUE), { V1 = pmax(as.character(v1), as.character(v2), na.rm = TRUE) ; rm(v1, v2)})....
  • 最后很容易转换回因子。

标签: r data-manipulation recode


【解决方案1】:

正如@Gregor 提到的,您可以将 df 转换回因子。这里方便的功能是@MrFlick 的coalesce 功能。解决方案一目了然

library(dplyr)

df.1 %>%
  left_join(df.2, by = "id") %>%
  mutate_if(is.factor, as.character) %>%
  mutate(final = coalesce(v1, v2))  %>% mutate_if(is.character, as.factor)

输出

   id      v1     v2   final
1  334  4 dogs   <NA>  4 dogs
2  440    <NA> 4 dogs  4 dogs
3  501  3 dogs   <NA>  3 dogs
4 2304    <NA> 5 dogs  5 dogs
5 2500 No dogs   <NA> No dogs

将上述结果存储在一个变量(df)中,然后检查str(df)

'data.frame':   5 obs. of  4 variables:
 $ id   : num  334 440 501 2304 2500
 $ v1   : Factor w/ 3 levels "3 dogs","4 dogs",..: 2 NA 1 NA 3
 $ v2   : Factor w/ 2 levels "4 dogs","5 dogs": NA 1 NA 2 NA
 $ final: Factor w/ 4 levels "3 dogs","4 dogs",..: 2 2 1 3 4

如果您想删除 v1v2 列,只需将最终结果通过管道传输到 %&gt;% select(id,final)

希望它有效。

【讨论】:

    【解决方案2】:

    使用data.tabledplyr:-

    library(data.table)
    library(dplyr)
    df <- left_join(df.1, df.2, by = "id")
    setDT(df)
    df[is.na(v1), v1 := v2]
    df[, v2 := NULL]
    

    你会得到想要的输出:-

         id      v1
    1:  334  4 dogs
    2:  440  4 dogs
    3:  501  3 dogs
    4: 2304  5 dogs
    5: 2500 No dogs
    

    到目前为止,id 将是数字,v1 将是因子。如果您想将id 也转换为因子。你可以这样做:-

    df[, id := as.factor(id)]
    

    【讨论】:

    • 使用这种方法,变量会丢失其因子类型吗?
    • 所以,v1 将是一个因素。 id 将是数字。如果你想再次制作id 因素。您可以使用df[, id := as.factor(id)]。如果你愿意,我会把它添加到答案中。
    • 抱歉,ID 始终是数字,并且可以作为唯一标识符保持数字。谢谢。
    • 酷,反正我加了。如果你需要,你可以使用它。
    • 刚刚使用了您的代码并查看了新创建的 v1 变量的摘要。似乎 'NA' 已添加为 df1 中所有未替换的缺失值的一个因素...您有解决方案将它们恢复为缺失值吗?
    【解决方案3】:

    使用tidyverse 方法,您有两种解决方案:

    第一个解决方案:

    library(dplyr)
    df.1 <- data.frame(id = c(334,440,501,2304,2500), 
                       v1 = c("4 dogs",NA,"3 dogs",NA,"No dogs"),stringsAsFactors=F) 
    
    df.2 <- data.frame(id = c(440,2304), 
                       v2 = c("4 dogs","5 dogs"),stringsAsFactors=F) %>% 
        rename(v1=v2)
    
    df_mix <- bind_rows(df.1,df.2) %>% 
        drop_na(...=v1)
    

    第二种解决方案:

    df.1 <- data.frame(id = c(334,440,501,2304,2500), 
                       v1 = c("4 dogs",NA,"3 dogs",NA,"No dogs"),stringsAsFactors=F)
    
    df.2 <- data.frame(id = c(440,2304), 
                       v2 = c("4 dogs","5 dogs"),stringsAsFactors=F) 
    
    df_mix <- left_join(df.1,df.2,by="id") %>% 
        mutate(v1=case_when(
            is.na(v1) ~ v2,
            !is.na(v1) ~ v1
        )) %>% 
        select(1:2)
    

    PS:我更喜欢将字符串作为字符向量加载

    【讨论】:

      【解决方案4】:

      您可以加入df.1df.2 以将v1v2 保留在合并的data.frame 中。将缺少的v1 替换为v2 的运行逻辑。

      library(dplyr)
      
      df.1 <- data.frame(id = c(334,440,501,2304,2500), 
                         v1 = c("4 dogs",NA,"3 dogs",NA,"No dogs"))
      
      df.2 <- data.frame(id = c(440,2304), 
                         v2 = c("4 dogs","5 dogs"))
      #merge using left_join to keep all rows from df.1
      final <- df.1 %>%
        left_join(df.2, by = "id")
      #> final
      #    id      v1     v2
      #1  334  4 dogs   <NA>
      #2  440    <NA> 4 dogs
      #3  501  3 dogs   <NA>
      #4 2304    <NA> 5 dogs
      #5 2500 No dogs   <NA>
      
      #Define a function to replace missing v1
      replMissing <- function(x, y){
        ifelse(is.na(x), y, x )
      }
      
      #call replMissing function using mapply. Modified to handle factor
      final$v1 <- as.factor(mapply(replMissing, as.character(final$v1), as.character(final$v2)))
      
      #results is
      #> final
      #    id      v1     v2
      #1  334  4 dogs   <NA>
      #2  440  4 dogs 4 dogs
      #3  501  3 dogs   <NA>
      #4 2304  5 dogs 5 dogs
      #5 2500 No dogs   <NA>
      

      现在可以删除v2

      【讨论】:

      • 是否有可能的解决方案,然后将它们改回一个因子并保留它原来的所有级别?
      • @dayleymart 修改解决方案以处理 factor 值。实际上在调用mapply时需要进行转换。
      猜你喜欢
      • 2021-06-17
      • 1970-01-01
      • 2022-01-03
      • 2015-10-30
      • 2017-09-21
      • 2020-07-22
      • 1970-01-01
      • 1970-01-01
      • 2020-05-04
      相关资源
      最近更新 更多