【问题标题】:Strange "NA.123" rows in an R data frameR数据框中奇怪的“NA.123”行
【发布时间】:2015-09-26 04:11:53
【问题描述】:

我在使用 R 时遇到了一个非常奇怪的问题。某些操作会在数据框中产生不是“真实”NA 的 NA 记录——它们在原始数据集中没有一行,行 ID 表示一些奇怪的东西,例如NA.123 而不是真正的行号,它们匹配 ==1 的测试。

很难描述正在发生的事情,所以我会让大量注释的代码来做大部分的讨论。此处引用的数据文件是一个来自 NHANES 2005 数据集的小型 (187 K) 公开可用文件,如果有人需要,可以在 http://wwwn.cdc.gov/Nchs/Nhanes/2005-2006/COT_D.XPT 上找到它,以便他们可以尝试复制问题。

我正在创建一个是/否变量来评估可替宁血液测试是阳性还是阴性,使用 10 的截止值来定义阳性测试。在下面的代码中,我以两种不同的方式执行此操作,创建“cotpos1”和“cotpos2”来说明我在解决此问题时发现的一些内容。

就本文而言,“良好的 NA”应该是 NA,因为原始验血结果缺失,而“不良 NA”是不属于原始血液的神秘行之一数据,每个值都是NA(包括SEQN,原始数据中的任何行都没有丢失),行号显示为NA.123,每列中的NA匹配==1。

此数据集使用名为 SEQN 的字段来识别每条记录。一开始,没有记录没有 SEQN,所以当“坏 NA”稍后出现并且它们的 SEQN 也是 NA(以及该行中的所有其他内容)时,这向我表明正在添加行。

还有其他方法可以做到这一点,不会产生“坏 NA”,比如使用 ifelse() 或使用重新编码的包,所以我的问题不在于如何使这项工作 - 它是“为什么下面代码中使用的方法会产生奇怪的 NA.123 行吗?"

library(foreign) # To open SAS xpt files

# Read in the data files
testdata <- read.xport('COT_D.xpt')

################# cotpos1, everything set to 0 or 1 #################

testdata$cotpos1[testdata$LBXCOT >= 10] <- 1 # Positive cotinine test
testdata$cotpos1[testdata$LBXCOT < 10] <- 0 # Negative cotinine test

testdata$cotpos1[testdata$cotpos1==1] # We have NAs that match ==1
testdata[testdata$cotpos1==1,c("SEQN","cotpos1")] # The bad NAs have no SEQN and their row numbers look like NA.988
testdata[is.na(testdata$cotpos1),c("SEQN","cotpos1")] # The good NAs (ones that are NA because LBXCOT was NA, and match is.na()) have SEQN and row numbers

################# cotpos2, with initialization to 0 #################

testdata$cotpos2 <- 0 # Assume everyone is negative until found otherwise
testdata$cotpos2[testdata$LBXCOT >= 10] <- 1 # Positive cotinine test

# 3 tests to show we have no "bad NAs" at this point
testdata$cotpos2[testdata$cotpos2==1] # No NAs that match ==1
testdata[testdata$cotpos2==1,c("SEQN","cotpos2")] # No lines with no SEQN values or strange row IDs like NA.988
testdata[is.na(testdata$cotpos2),c("SEQN","cotpos2")] # No good NAs either because we initialized everyone to 0

# Now let's try finding the "good NA"s and setting them to NA (since they were initialized to 0, which is not accurate if the blood test results were actually missing)
testdata$cotpos2[is.na(testdata$LBXCOT)] <- NA

# Re-run the three tests, and they now show the bad NAs are back as well
testdata$cotpos2[testdata$cotpos2==1] # Now there are NAs that match ==1
testdata[testdata$cotpos2==1,c("SEQN","cotpos2")] # Now there are lines with NA SEQN values and strange row IDs like NA.988
testdata[is.na(testdata$cotpos2),c("SEQN","cotpos2")] # These are the "good NAs" only, the bad ones don't show up here

还有其他方法可以做到这一点,不会产生“坏 NA”,比如使用 ifelse() 或使用重新编码的包,所以我的问题不在于如何使这项工作 - 它是“为什么上面代码中使用的方法会产生奇怪的 NA.988 行吗?”

响应 BondedDust 的更多信息: 感谢你的回复。您能否澄清一下您指的是 [] 的哪个怪癖?

我知道如果你给它一个 NA,你会得到一个全 NA 行,例如:

b = testdata$cotpos1==1
b
testdata[b,c("SEQN","cotpos1")]

那么任何地方 b 是 NA 我应该期望最后一行返回一个 NA。是你指的那个吗?不幸的是,在我的代码中,问题在于奇怪的 NA 行出现在 b 不是 NA 的地方,因此怪癖无法解释它。

这是 b 的最后几行:

[8725]  TRUE    NA FALSE FALSE    NA  TRUE FALSE FALSE FALSE FALSE FALSE    NA
[8737] FALSE    NA FALSE FALSE FALSE  TRUE FALSE FALSE FALSE FALSE FALSE  TRUE
[8749]  TRUE FALSE  TRUE FALSE FALSE

这里是 testdata[b,c("SEQN","cotpos1")] 的最后几行:

8711   41422       1
NA.986    NA      NA
NA.987    NA      NA
8722   41437       1
8725   41440       1
NA.988    NA      NA
NA.989    NA      NA
8730   41447       1
NA.990    NA      NA
NA.991    NA      NA
8742   41461       1
8748   41468       1
8749   41469       1
8751   41472       1

奇怪的 NA 出现在 b 不是 NA 的地方

最终编辑: BondedDust 的回答是正确的。当我说 b 和奇怪的 NA 不匹配时(上图),我没有考虑到 [] 不打印对应于 FALSE 的行的事实。一旦你去掉假的,它们就完美匹配了。

【问题讨论】:

  • 我猜你看到了我认为 R "[" 函数的不合理之处。其他人,包括 R Core,认为这是一个特性。如果您使用包含 NA 值的向量选择数据帧的行(或向量中的值),您将在该级别/行中获得一行(或单个值)NA - 无论结果如何。你应该学会修剪你的数据集,使它们成为一个“最小的”可重复的例子。
  • 大概也和dplyr,data.table一起消失了

标签: r indexing dataframe na


【解决方案1】:

如果您查看 testdata$cotpos2 的值,您会看到:

> table( testdata$cotpos2==1, useNA="always")

FALSE  TRUE  <NA> 
 6346  1415   992 

阅读“[”函数的帮助页面。它可以阅读大约 10 次。您应该找到描述“[”在给定 NA 值时的行为的部分。当理解其规则和细微之处是 R 中有效数据管理的关键。(我会在 NA 值的处理方面对其进行不同的设计。)

【讨论】:

  • 感谢您的回复。您能否澄清一下您指的是 [] 的哪个怪癖?我知道如果你喂它 c(TRUE,TRUE,NA,TRUE) 它将为 NA 返回一个全 NA 行,问题是这些全 NA 行出现在 testdata 结果的地方$cotpos1==1 是不是 NA。由于 cmets 有字符限制,因此我在上面的原始问题中添加了一个示例。
  • ...aaa 我刚刚意识到您的答案是正确的,而我对它的阅读是错误的。当我倒数比较 cotpos2==1 和 [] 的结果时,我应该只计算“TRUE”,“FALSE”不会显示,因为它们是错误的。这样算下来,它们完全匹配,所以这就是 [] 的怪癖。谢谢!
  • 请说明“[”的具体怪癖是什么?否则这不是答案。
  • 我认为我称之为不正当的“怪癖”在评论中得到了充分的描述。这个“答案”确实是希望被视为评论中分析有效性的证明。
  • smci - BondedDust 所说的怪癖/不合理之处是,如果您输入 [] 一个 NA,它将返回其中一个神秘行。因此,如果我有一个 == 评估为 NA (就像 NA==1 一样),那么结果将是一个全 NA 行,即使原始行在其他字段中有数据。 BondedDust 的回答足以为我指明正确的方向,我接受它作为答案,因为它帮助我解决了问题。谢谢你们!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-12-13
  • 2021-03-24
  • 1970-01-01
  • 2020-09-13
  • 1970-01-01
  • 2015-12-06
相关资源
最近更新 更多