【问题标题】:"NAs are not allowed in subscripted assignments"“下标作业中不允许使用 NA”
【发布时间】:2016-03-17 14:50:30
【问题描述】:

我有一个数据框,其中包含一些缺失值,我想从另一个日期框中获取并插入到第一个中。当我要补充的值在第一个数据帧的所有行中缺失时,此方法有效。

这是一个工作示例:

dat <- data.frame(code = c("A11", "B22"),
                  age = c(NA, NA),
                  sex = c(NA, NA),
                  more = c(7, 4),
                  stringsAsFactors = FALSE)

age.and.sex <- read.table(textConnection("
code age sex
A11 15 m
B22 10 f
"), header = TRUE, stringsAsFactors = FALSE)

dat$sex[match(dat$code, age.and.sex$code)] <- age.and.sex$sex
dat$age[match(dat$code, age.and.sex$code)] <- age.and.sex$age

dat
  code age sex more
1  A11  15   m    7
2  B22  10   f    4

问题是,当我没有从最火的数据框中的所有行中丢失值,但我只需要补充某些行时,我会收到错误。

这是一个不起作用的例子:

dat <- data.frame(code = c("A11", "B22", "C33"),
                  age = c(NA, NA, 12),
                  sex = c(NA, NA, "m"),
                  more = c(7, 4, 9),
                  stringsAsFactors = FALSE)

age.and.sex <- read.table(textConnection("
code age sex
A11 15 m
B22 10 f
"), header = TRUE, stringsAsFactors = FALSE)

dat$sex[match(dat$code, age.and.sex$code)] <- age.and.sex$sex
Error in dat$age[match(dat$code, age.and.sex$code)] <- age.and.sex$age : 
  NAs are not allowed in subscripted assignments
dat$age[match(dat$code, age.and.sex$code)] <- age.and.sex$age
Error in dat$age[match(dat$code, age.and.sex$code)] <- age.and.sex$age : 
  NAs are not allowed in subscripted assignments

我不明白 R 返回的错误。

我需要如何更改我的代码才能让它再次工作?

我想要达到的结果是:

dat
  code age sex more
1  A11  15   m    7
2  B22  10   f    4
3  C33  12   m    9

感谢大家迄今为止的帮助。但我必须承认,我对你的解决方案不太满意。

您建议采用四步方法:将一个数据框添加到另一个数据框,将值一个一个移动到所需的目的地,然后删除现在多余的辅助列。作为架构,您的解决方案如下所示:

这对我来说似乎非常复杂!

当我查看我的数据时,对我来说似乎显而易见的解决方案只有一个步骤:从一个数据帧中剪切“矩阵”并将其粘贴到另一个数据帧的“空白”区域。这是我脑海中的样子:

显然这实际上是可能的:

dat[1:2,2:3] <- age.and.sex[1:2,2:3]
dat
  code age sex more
1  A11  15   m    7
2  B22  10   f    4
3  C33  12   m    9

当然,这仅适用于两个数据帧以相同方式排序的情况。这就是我使用match() 的原因,它克服了行不排序时的问题——但在行数不同时会失败。

或者有没有办法match(),即使行数不一样?

【问题讨论】:

  • 你在做x[match(y,z)] &lt;- wmatch(y,z) 里面有一些NA,所以它不能分配。
  • 我可能会使用更多的“左连接,然后合并/ifelse 缺少值的列”的策略。
  • @what...我打错了...忘记了by部分。应该阅读merge(dat, age.and.sex, by="code", all.x=TRUE)
  • 这似乎有效:cbind(code=dat[,1],rbind(age.and.sex[,2:3],dat[3,2:3]),more=dat[,4])
  • 不要避免学习加入!要意识到的是,即使您确实找到了使用match 的解决方案,您基本上还是手动计算连接,然后查找连接的列。所以本质上你是在重新发明轮子。想想你原来的match 解决方案的逻辑:“在age.and.sex 中找到code 列与dat 中的行匹配的行,然后从age.and.sex 中获取相应的其他列。”好吧,这正是连接(或 merge)的工作方式:从连接表中查找第一个表中 by 列匹配的列。

标签: r


【解决方案1】:

您正在尝试分配给这三行:

> match(dat$code, age.and.sex$code)
[1]  1  2 NA

因为dat$codeage.and.sex$code长度不一样,所以第三个比较的是NA

我不确定您实际上要匹配什么,但您可以尝试对前两个观察值进行子集化,或 na.omit 等。

但连接两个表中的数据的更好方法是使用join

library(data.table)
dat <- data.table(dat)
setkey(dat,code)
age.and.sex <- data.table(age.and.sex)
setkey(age.and.sex,code)
dat[age.and.sex]
> dat[age.and.sex]
   code age sex more i.age i.sex
1:  A11  NA   m    7    15     m
2:  B22  NA   f    4    10     f

注意内部表的列是如何附加到外部表的列的。

更多...根据@joran 的建议...您可以使用这种技术来填补缺失的观察结果:

joined <- dat[age.and.sex]
joined[is.na(age),age:=i.age] #only replace the value missing from left table
joined[,c("i.age","i.sex"):=NULL]
joined
> joined
   code age sex more
1:  A11  15   m    7
2:  B22  10   f    4

更新以解决您的评论...只需反转加入即可。有一些更聪明的方法可以减少手动操作,但这应该很容易遵循:

joined <- age.and.sex[dat]
joined[is.na(age),age:=i.age]
joined[is.na(sex),sex:=i.sex]
joined[,c("i.age","i.sex"):=NULL]
> joined
   code age sex more
1:  A11  15   m    7
2:  B22  10   f    4
3:  C33  12   m    9

如果您喜欢这种技术,您绝对应该阅读?data.table 和相关的vignette 以了解有关联接的更多信息。

【讨论】:

  • 顺便说一句,我刚刚用一种显示(我认为是)最佳方法的方法更新了答案。让我知道这是否能解决您的问题。
  • 为什么不直接join+updatesetDT(dat)[age.and.sex, c("age", "sex") := .(i.age, i.sex), on="code"][]?
  • 是的——非常好,以下根本不是分歧,而且这个建议更好......但正如答案中所述,虽然有更快,更少罗嗦,更优雅的方法这样做,OP 对data.table 来说显然是新的,我认为看到事情一步一步完成,OP 可以跟踪 REPL 中的输出在教学上更合理。我们不知道 OP 的 MWE 是否正是 OP 的用例,或者实际上只是一个 MWE,其某些方面不能代表原始问题。
  • 如果是后者,OP 可能更容易从更详细的示例中概括到实际问题,无论哪种方式,OP 都将从了解您的建议如何工作中受益. (可能在学习了更简单的形式之后。)最好的
  • @Philip 你说得对,我是data.table 的新手,从你的例子中学到了很多东西。但正如您从我最近对我的问题的编辑中看到的那样,我对数据的看法与您不同,即更多地以视觉方式 - 就好像它打印在纸上一样,我可以从一张表中剪切数据并将其粘贴到另一个。这阻碍了我——它让我想要以不同的方式做这件事;-)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-05-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多