【问题标题】:replace missing column values with values from 'matching' columns用“匹配”列中的值替换缺失的列值
【发布时间】:2017-07-19 00:02:12
【问题描述】:

这是来自的后续问题 replace missing values with a value from another column 已充分解决。我的问题是关于多个匹配列。

示例数据集:

s <- data.frame(ID=c(191, 282, 202, 210), 
            Group.1=c(NA, "A", NA, "B"), 
            Back.1=c("DD", "AA", "DD", "BB"), 
            Group.2=c("D","A", NA, "B"),
            Back.2=c("DD", "BB", "CC", "AA"),
            stringsAsFactors=FALSE)

   ID Group.1 Back.1 Group.2 Back.2
1 191    <NA>     DD       D     DD
2 282       A     AA       A     BB
3 202    <NA>     DD    <NA>     CC
4 210       B     BB       B     AA

如果我想用匹配的“Back”列替换 NA,我会使用:

s$Group.1 <- ifelse(test = !is.na(s$Group.1), yes = s$Group.1, no = s$Back.1)
s$Group.2 <- ifelse(test = !is.na(s$Group.2), yes = s$Group.2, no = s$Back.2)
s

   ID Group.1 Back.1 Group.2 Back.2
1 191      DD     DD       D     DD
2 282       A     AA       A     BB
3 202      DD     DD      CC     CC
4 210       B     BB       B     AA

正如 Akrun 所发布的,另一种方法是:

library(data.table)
setDT(s)[is.na(Group.1), Group.1:= Back.1]
setDT(s)[is.na(Group.2), Group.2:= Back.2]

因此,如果我有许多匹配的列,我希望能够映射、循环或应用它们之间的任何内容。尝试循环函数产生:

for (i in 1:2){
  s[paste0("Group.", i)] <- ifelse(test = !is.na(s[paste0("Group.", i)]), 
                                   yes = s[paste0("Group.", i)], 
                                   no = s[paste0("Back.", i)])
}

Warning messages:
1: In `[<-.data.frame`(`*tmp*`, paste0("Group.", i), value = list(c("DD",  :
  provided 4 variables to replace 1 variables
2: In `[<-.data.frame`(`*tmp*`, paste0("Group.", i), value = list(c("D",  :
  provided 4 variables to replace 1 variables
> s
   ID Group.1 Back.1 Group.2 Back.2
1 191      DD     DD       D     DD
2 282      AA     AA       A     BB
3 202      DD     DD    <NA>     CC
4 210      BB     BB       B     AA

这似乎适用于 Group.1 和 Back.1 但不适用于 Group.2,从我的角度来看,警告消息很难理解。

如果有人可以通过适当的循环解决这个问题,将不胜感激。更有用的是泛化到其他命名列的能力,以便与 Back.x 数字匹配的列也可以包含由 Back.x 估算的缺失值。即

s <- data.frame(ID=c(191, 282, 202, 210), 
            Group.1=c(NA, "A", NA, "B"), 
            Back.1=c("DD", "AA", "DD", "BB"), 
            Group.2=c("D","A", NA, "B"),
            Back.2=c("DD", "BB", "CC", "AA"),
            Donk.1 =c("PP", "ZZ", NA, "QQ"),
            stringsAsFactors=FALSE)

【问题讨论】:

  • 为什么你有2列名字叫Back.1
  • 如果您以长格式long &lt;- reshape(s, direction="long", idvar="ID", varying=-1) 执行此操作,则将无限容易,然后只需将long$Group 替换为缺少的long$Back
  • 预期的“Donk.1”是什么?
  • 抱歉@waterling 捡回来了。1 被添加了两次。应该只有一次。稍后会编辑
  • 在上一个示例中不清楚应该从哪些列替换哪个?你有 Back.1、Back.2 和 Back.1.1,而有 Group.1、Group.2 和 Donk.1

标签: r missing-data


【解决方案1】:

我们可以使用

gr1 <- grep("Group", names(s), value = TRUE)
bc1 <- grep("Back", names(s), value = TRUE)
setDT(s)
for(j in seq_along(gr1)){
    s[is.na(get(gr1[j])), (gr1[j]) := get(bc1[j])]
}

s
#    ID Group.1 Back.1 Group.2 Back.2
#1: 191      DD     DD       D     DD
#2: 282       A     AA       A     BB
#3: 202      DD     DD      CC     CC
#4: 210       B     BB       B     AA

对于更新的数据集

gr1 <- names(s)[seq(2, ncol(s), by = 2)]
bc1 <- names(s)[seq(3, ncol(s), by = 2)]

setDT(s)
for(j in seq_along(gr1)){
    s[is.na(get(gr1[j])), (gr1[j]) := get(bc1[j])][]
}
s
#    ID Group.1 Back.1 Group.2 Back.2 Donk.1 Back.1.1
#1: 191      DD     DD       D     DD     PP       DD
#2: 282       A     AA       A     BB     ZZ       AA
#3: 202      DD     DD      CC     CC     DD       DD
#4: 210       B     BB       B     AA     QQ       BB

数据

s <- data.frame(ID=c(191, 282, 202, 210), 
        Group.1=c(NA, "A", NA, "B"), 
        Back.1=c("DD", "AA", "DD", "BB"), 
        Group.2=c("D","A", NA, "B"),
        Back.2=c("DD", "BB", "CC", "AA"),
        Donk.1 =c("PP", "ZZ", NA, "QQ"),
        Back.1=c("DD", "AA", "DD", "BB"), 
        stringsAsFactors=FALSE)

【讨论】:

  • 将 gr1 替换为 gr1&lt;- grep("^(?!Back).*\\.[0-9]+$",names(s), perl=T, value=TRUE),将 bc1 替换为 bc1&lt;-paste("Back",sub(".*\\.([0-9])+", "\\1", rInd),sep=".")
  • @waterling 抱歉,我不明白为什么需要它。我正在尝试基于 OP 代码中提供的逻辑setDT(s)[is.na(Group.1), Group.1:= Back.1]
  • OP 希望能够将Donk.1 替换为Back.1,或将部分arbitrarytext.Number 替换为Back.Number。来自句子:“泛化到其他命名列,以便与 Back.x 的数值匹配列也可以具有由 Back.x 估算的缺失值”
  • @waterling 谢谢我错过了那部分。我更新了帖子,假设列是交替的
猜你喜欢
  • 1970-01-01
  • 2023-01-13
  • 1970-01-01
  • 2017-06-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-10-11
相关资源
最近更新 更多