【问题标题】:Removing "NA" values in R (for some reason na.omit and complete.cases only work on one variable...)删除 R 中的“NA”值(出于某种原因 na.omit 和 complete.cases 仅适用于一个变量......)
【发布时间】:2019-01-18 00:36:45
【问题描述】:

此作业的第一部分是从外部 http 站点导入数据;数据包含 8 个变量和 1,339 个观测值。其中四个变量(年龄、身高、体重、igf1)在其中包含 NA 值(注意:其他变量也可能具有 NA 值,但我不关心它们)。我需要消除这四个变量中的 NA 值:这就是我苦苦挣扎的地方。

这是我目前所拥有的:

#imports dataset from internet
importData <- read.table("http://people.sc.fsu.edu/~jburkardt/datasets/iswr/juul2.csv", sep=',', header=T)
#inspects the data:
str(importData)

基本上,我想删除年龄、身高、体重和 igf1 中的所有 NA 值。当我还有 858 个观察值时,我就知道我成功了。

其中三个变量(身高、体重、igf1)包含 FACTOR 类型信息。变量之一(年龄)包含数字信息。我一直无法在它们之间成功实现 complete.cases 和/或 na.omit:这些函数似乎只适用于 $age,它们消除了五个 NA 值(但不要触及其他变量)

我需要帮助删除剩余变量中的 NA 值。同样,当我完成后,我应该有 858 个观察结果。

【问题讨论】:

  • 欢迎来到 SO!您应该尝试提供reproducible example。至于您的问题,当您说“删除”时,您的意思是:(a) 删除所有四个中包含 NA 的行? (b) 删除其中任何一个包含NA 的行?或 (c) 将 NA 更改为另一个值(估算)?
  • 我偶尔会在不知不觉中设法将 NA 转换为字符串“NA”,从而导致各种下游问题。检查您是否没有管理相同的内容。
  • 谢谢你,休。对于您的问题,我的意思是 (A) 在所有四个变量中删除包含 NA 的行。我想完全删除行,而不是替换值。
  • 我们能看到str(data)吗? (complete.cases不应该在任何列中留下NAs,这不是您想要的,但您似乎还有其他问题。)
  • 感谢休和理查德。请参阅上面的修改。

标签: r


【解决方案1】:

问题是您的数据文件将所有值括在引号中,如下所示:

"age", "height", "menarche", "sex", "igf1", "tanner", "testvol", "weight"
"NA", "NA", "NA", "NA", "90.0", "NA", "NA", "NA"
"NA", "NA", "NA", "NA", "88.0", "NA", "NA", "NA"

当 R 读取它时,它将所有值作为字符串,默认情况下表示为因子。 NAs 只是作为这些因素的一个级别的标签。你可以通过str看到这个:

> str(importData)
'data.frame':   1339 obs. of  8 variables:
 $ age     : num  NA NA NA NA NA 0.17 0.17 0.17 0.17 0.17 ...
 $ height  : Factor w/ 600 levels " 110.8"," 111.5",..: 600 600 600 600 600 600 600 600 600 600 ...
 $ menarche: Factor w/ 3 levels " 1"," 2"," NA": 3 3 3 3 3 3 3 3 3 3 ...
 $ sex     : Factor w/ 3 levels " 1.00"," 2.00",..: 3 3 3 3 3 1 1 1 1 1 ...
 $ igf1    : Factor w/ 501 levels " 100.0"," 101.0",..: 490 487 53 55 23 2 498 6 10 474 ...
 $ tanner  : Factor w/ 6 levels " 1"," 2"," 3",..: 6 6 6 6 6 1 1 1 1 1 ...
 $ testvol : Factor w/ 26 levels " 1"," 10"," 11",..: 26 26 26 26 26 26 26 26 26 26 ...
 $ weight  : Factor w/ 518 levels " 14.1"," 17.9",..: 518 518 518 518 518 518 518 518 518 518 ...

所以在不考虑因素的情况下读取您的数据,所有因素都读取为数字:

> importData <- read.csv("http://people.sc.fsu.edu/~jburkardt/datasets/iswr/juul2.csv",
                         stringsAsFactors=F, na.strings=c(NA,"NA"," NA"))
> str(importData)
'data.frame':   1339 obs. of  8 variables:
 $ age     : num  NA NA NA NA NA 0.17 0.17 0.17 0.17 0.17 ...
 $ height  : num  NA NA NA NA NA NA NA NA NA NA ...
 $ menarche: int  NA NA NA NA NA NA NA NA NA NA ...
 $ sex     : num  NA NA NA NA NA 1 1 1 1 1 ...
 $ igf1    : num  90 88 164 166 131 101 97 106 111 79 ...
 $ tanner  : int  NA NA NA NA NA 1 1 1 1 1 ...
 $ testvol : int  NA NA NA NA NA NA NA NA NA NA ...
 $ weight  : num  NA NA NA NA NA NA NA NA NA NA ...

现在删除NAs:

> data <- importData[complete.cases(importData[c("age","height","weight","igf1")]),]
> str(data)
'data.frame':   858 obs. of  8 variables:
 $ age     : num  6 6.08 6.26 6.4 6.42 6.43 6.61 6.63 6.7 6.72 ...
 $ height  : num  112 117 120 116 116 ...
 $ menarche: int  NA NA NA NA NA NA NA NA NA NA ...
 $ sex     : num  1 1 1 1 1 1 1 1 1 1 ...
 $ igf1    : num  98 242 196 179 126 142 236 148 174 136 ...
 $ tanner  : int  1 1 1 1 1 1 1 1 1 1 ...
 $ testvol : int  1 1 1 1 1 1 1 2 1 1 ...
 $ weight  : num  19.1 21.7 24.7 19.6 20.6 20.2 28 21.6 26.1 22.6 ...

【讨论】:

  • 这明白了。它实际上非常接近我尝试过的许多事情,但我自己从来没有完全做到过。谢谢!
【解决方案2】:

为什么不减轻压力,转而阅读.txt 版本的数据呢?我在与.csv 相同页面的数据列表中找到它。它没有像.csv 文件那样异常间隔,也没有摆弄read.csv 参数(我在找到另一个文件之前做了很长一段时间)。

con <- "http://people.sc.fsu.edu/~jburkardt/datasets/iswr/juul2.txt"
dat <- read.table(con, header = TRUE)
sapply(dat, class)
#       age    height  menarche       sex      igf1    tanner   testvol    weight 
# "numeric" "numeric" "integer" "numeric" "numeric" "integer" "integer" "numeric" 
cols <- c("age", "height", "weight", "igf1")
resultSet <- dat[complete.cases(dat[cols]), ]
dim(resultSet)
# [1] 858   8

【讨论】:

  • 过于本地化,但 +1 以获得最佳解决方案!
【解决方案3】:

使用as.is=TRUEna.strings = c(NA, "NA", " NA")) 读入您的数据。您的文件在字段之间有空格,这些空格被解释为字段的一部分。

data <- read.table("http://people.sc.fsu.edu/~jburkardt/datasets/iswr/juul2.csv", 
        sep=",", header=TRUE, as.is=TRUE, na.strings=c(NA, "NA", " NA"))

如果要删除 任何 所选列为 NA 的行,请使用 complete.cases

new.data <- data[complete.cases(data[ ,c("age", "height", "weight", "igf1")]), ]
nrow(new.data)
# [1] 858

如果您只想删除 所有 所选列为 NA 的行,请使用 rowSums

new.data <- data[rowSums(is.na(data[ ,c("age", "height", "weight", "igf1")])) < 4, ]
nrow(new.data)
# [1] 1339   # there aren't any such rows :)

这隔离了四列,测试它们是否为NA,并为每一行计算有多少是NA,只返回每行少于4 个NAs 的那些。

【讨论】:

  • 谢谢,休。实现这一点,我仍然有 1,339 个观察结果 - 这告诉我它没有删除 NA 值?请参见示例: > test1 str(test1) '数据帧':1339 obs。 8 个变量
  • 您确定有要删除的行吗?我看不到任何符合描述的行。 (只有 5 行有 age NA 并且它们在列中只有三个 NAs。)
  • 谢谢,休。我刚刚编辑了上面的所有内容,希望能更清楚。
  • 您实际上想要的是选项 (b),而不是选项 (a)。
  • 谢谢你,休。我在原帖中有点不清楚,对此感到抱歉。再次感谢您的帮助!
【解决方案4】:

如果您正在从文件中读取数据,请使用下面的 read.table 选项:

read.table(...,quote="")

如果您有条件地创建了 NA,例如:

df[condition] <- NA

确保你从不使用它引用(“NA”)。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-10-12
    • 1970-01-01
    • 2016-05-10
    • 1970-01-01
    • 2011-01-22
    相关资源
    最近更新 更多