【发布时间】: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一起消失了