【问题标题】:Replace NA's belonging to one column with values from another column用另一列中的值替换属于一列的 NA
【发布时间】:2015-11-09 10:14:23
【问题描述】:

我有以下数据框(命名为“df”),列名称为 ID、org1 和 org2。

结构:

 ID  org1  org2
 1    C1   NA
 2    C2   NA
 3    C3   C3
 4    C4   C4
 5    C1   NA
 6    NA   C2
 7    NA   C4
 8    NA   NA
 9    NA   NA
 10   C3   C3

现在,我希望 org1 从 org2 获取值,以防 org1 中出现“NA”,例如:ID 6

预期输出:

 ID  org1  org2
 1    C1   NA
 2    C2   NA
 3    C3   C3
 4    C4   C4
 5    C1   NA
 6    C2   C2
 7    C4   C4
 8    NA   NA
 9    NA   NA
 10   C3   C3

我厌倦了以下内容:

   df$org1[is.na(df$org1)] <- as.character(df$org2[is.na(df$org1)])

指以下:Replace NA in column with value in adjacent column

但这产生了以下错误:

  Warning message:
  In `[<-.factor`(`*tmp*`, is.na(df$org1),  :invalid factor level, NA generated

谁能告诉我我做错了什么,有没有更好的解决方案。

【问题讨论】:

    标签: r dataframe missing-data


    【解决方案1】:

    通过使用lapply 循环遍历factor 列,将factor 列转换为character 类。

      df1[-1] <- lapply(df1[-1], as.character)
    

    然后我们可以使用pmaxpmax 将获得两列之间的逐行最大元素。由于 'org2' 与 'org1' 几乎相同,除了 NA 值,pmaxna.rm=TRUE 在有一个 NA 和非 NA 时删除 NA 元素,或者如果有两个 NA 返回NA,或者有两个非 NA 相同的返回唯一元素。

    df1$org1 <- do.call(pmax, c(df1[-1], list(na.rm=TRUE)))
    df1
    #   ID org1 org2
    #1   1   C1 <NA>
    #2   2   C2 <NA>
    #3   3   C3   C3
    #4   4   C4   C4
    #5   5   C1 <NA>
    #6   6   C2   C2
    #7   7   C4   C4
    #8   8 <NA> <NA>
    #9   9 <NA> <NA>
    #10 10   C3   C3
    

    或者使用基于is.na的逻辑索引,根据索引对'org1'进行子集化,并将其替换为'org2'的对应元素。

     ind <- is.na(df1$org1)
     df1$org1[ind] <- df1$org2[ind] 
    

    或者正如 @David Arenburg 在 cmets 中提到的,我们可以 data.table 更快地分配。我们将 'data.frame' 转换为 'data.table' (setDT(df1)),使用 'i' 中的逻辑条件,我们将 'org1' 分配为 'org2' 对应于 'i'。

    library(data.table)
    setDT(df)[is.na(org1), org1 := org2]   
    

    数据

    df1 <- structure(list(ID = 1:10, org1 = structure(c(1L, 2L, 3L, 4L,   
     1L, NA, NA, NA, NA, 3L), .Label = c("C1", "C2", "C3", "C4"),
     class = "factor"), 
    org2 = structure(c(NA, NA, 2L, 3L, NA, 1L, 3L, NA, NA, 2L
    ), .Label = c("C2", "C3", "C4"), class = "factor")), .Names = c("ID", 
    "org1", "org2"), row.names = c(NA, -10L), class = "data.frame")
    

    【讨论】:

    • setDT(df)[is.na(org1), org1 := org2]
    • 我收到了 15 条警告,但这没有帮助
    • @user3875610 根据输入数据(假设您有错误中的因子列),我没有收到任何警告。
    • @akrun,是的,它有一些因素,但我厌倦了它工作的样本数据,尽管我发现大卫的解决方案要容易得多。 Akrun 你能解释一下你的代码到底做了什么
    • 感谢 akrun 和 David,您的解决方案都有效!!
    【解决方案2】:

    options(stringAsFactors =F) 会将所有列变成字符串(as.character)

    options(stringsAsFactors = F)
    mydf <- data.frame(ID = 1:10, org1 = c('C1','C2','C3','C4','C1',NA,NA,NA,NA,'C3'),
                       org2 = c(NA,NA,'C3','C4',NA,'C2','C4',NA,NA,'C3'))
    mydf$org1[is.na(mydf$org1)] <- mydf$org2[is.na(mydf$org1)]
    

    【讨论】:

    • 这已经在另一个答案中引入,只是没有使用which,这是多余的。
    • 是的,这是多余的,做了改变
    • 但这已经出现在另一个答案中,如前所述。
    猜你喜欢
    • 1970-01-01
    • 2016-03-08
    • 1970-01-01
    • 2019-06-01
    • 2019-08-23
    • 2022-07-15
    • 2020-05-18
    • 2020-08-13
    • 1970-01-01
    相关资源
    最近更新 更多