【问题标题】:How to replace NA values in R depending on the value of another column?如何根据另一列的值替换 R 中的 NA 值?
【发布时间】:2020-07-07 17:41:24
【问题描述】:

我有以下问题:

作为一个例子,我有这个数据框

> employee <- c('John Doe','Peter Gynn','Jolie Hope')
> salary <- c(NA, NA, NA)
> startdate <- as.Date(c('2010-11-1','2008-3-25','2007-3-14'))
> employ.data <- data.frame(employee, salary, startdate)

我定义了这个列表

> l <- list("John Doe" = "23400", 
               "Peter Gynn" = "28000",
               "Jolie Hoper" = "34000")

现在,我正在尝试根据员工列的值并使用列表替换薪水列中的 NA 值。 dplyr 有没有快速的方法?我正在寻找不同的情况,因为我在列表中有很多关键值...谢谢!

【问题讨论】:

    标签: r dplyr


    【解决方案1】:

    您可以使用dplyr 执行此操作,如下所示:

    library(dplyr)
    employ.data %>%
        mutate(
            salary = unlist(ifelse(is.na(salary) & employee %in% names(l), l[employee], salary))
        )
    

    【讨论】:

    • 嗨!它有效,但现在我遇到了另一个问题。它将列转换为列表,我无法在 csv 中导出数据框。我正在尝试这个:write_excel_csv(employ.data, "out/csv/data.csv")
    • 嗨 Razvan,这在小例子中似乎没有发生,或者我没有看到它发生.. 将 ifelse(...) 包装在 unlist 调用中会为您解决问题还是会引发错误?
    • 可能需要use.names=F。所以:unlist(fields(...), use.names=F)
    • 非常感谢!它可以在unlist 中包装对l[employee] 的调用,如下所示:library(dplyr) employ.data %&gt;% mutate(salary = ifelse(is.na(salary), unlist(l[employee], use.names=F), salary))
    • 实际上,unlist 潜入了一个危险的错误!使用您的上述行,不存在的“朱莉希望”将被分配薪水,这是错误的!我还没有调整我上面的答案来抓住它。
    【解决方案2】:

    你可以使用merge:

    #1. Convert your list to data.frame
    
        salaries <- data.frame(employee = names(l), salary = unlist(l))
    
    #2. Merge `salaries` with `employ.data`
    
        merge(salaries, employ.data,  by = "employee", all = TRUE)[-3]
            employee salary.x  startdate
        1   John Doe    23400 2010-11-01
        2 Jolie Hope    34000 2007-03-14
        3 Peter Gynn    28000 2008-03-25
    

    请注意,在我的示例中只有Jolie Hope,您还有Jolie Hoper 我不知道这是不是一个错字。不过,如果Jolie Hoper 在您的列表中,此解决方案也可以使用。

    【讨论】:

      【解决方案3】:

      我们可以在stack将命名的list 连接到两列data.frame 之后,使用连接ondata.table

      library(data.table)
      setDT(employ.data)[stack(l), salary := values, on = .(employee = ind)]
      employ.data
      #     employee salary  startdate
      #1:   John Doe  23400 2010-11-01
      #2: Peter Gynn  28000 2008-03-25
      #3: Jolie Hope  34000 2007-03-14
      

      或在base R 中,根据名称进行简单的子集化

      employ.data$salary <-  with(employ.data, unlist(l[employee]))
      

      数据

      l <- list("John Doe" = 23400, 
                 "Peter Gynn" = 28000,
                 "Jolie Hope" = 34000)
      employee <- c('John Doe','Peter Gynn','Jolie Hope')
      salary <-  rep(NA_real_, 3)
      startdate <- as.Date(c('2010-11-1','2008-3-25','2007-3-14'))
      employ.data <- data.frame(employee, salary, startdate)
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2016-03-08
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-05-18
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多