0

使用示例数据框:

df <- structure(list(
  KY27PHY1 = c("4", "5", "5", "4", "-", "4", "2","3", "5", "-", "4", "3", "3", "5", "5"),
  KY27PHY2 = c("4", "4","4", "4", "-", "5", "2", "3", "5", "-", "5", "3", "3", "5", "5"),
  KY27PHY3 = c("5", "4", "4", "4", "-", "5", "1", "4", "5","-", "4", "3", "3", "5", "5")),
                .Names = c("KY27PHY1", "KY27PHY2","KY27PHY3"),
                row.names = 197:211,
                class = "data.frame")

我一直在使用以下代码将值转换为数字:

df$KY27PHY1<-as.numeric(df$KY27PHY1)
df$KY27PHY2<-as.numeric(df$KY27PHY2)
df$KY27PHY3<-as.numeric(df$KY27PHY3)

由于我在 df 数据框中缺少值,因此我总是收到警告消息:

Warning message:
NAs introduced by coercion 

我认为这不是问题,但我只是想要一些关于如何改进代码的建议,所以我没有收到此消息。

另外,我如何一次完成所有列(按名称指定)?

提前谢谢了。

4

4 回答 4

2

我看到两种可能性:

  1. 不太可能的是您在 R 中构建了 data.frame。然后,只需更改代码以首先创建整数向量,或替换-NA这样as.numeric转换就不会抱怨。

  2. 更有可能的是您的 data.frame 来自 R 外部,您可能使用read.tableorread.csv函数之一读取它。然后只需添加na.strings = "-"到您的调用中,R 就会知道这些-将被理解为NA. 此外,如果这些列中没有其他奇怪的项目,则在这些type.convert函数中调用的函数将自动检测这些列是否为整数列并将它们存储起来。

于 2013-08-23T11:37:12.117 回答
1

data.table超级快,你应该在使用data.frames. 你的问题是:

library(data.table)
dt = as.data.table(df)
dt[,lapply(.SD,as.numeric)]
    KY27PHY1 KY27PHY2 KY27PHY3
 1:        4        4        5
 2:        5        4        4
 3:        5        4        4
 4:        4        4        4
 5:       NA       NA       NA
 6:        4        5        5
 7:        2        2        1
 8:        3        3        4
 9:        5        5        5
10:       NA       NA       NA
11:        4        5        4
12:        3        3        3
13:        3        3        3
14:        5        5        5
15:        5        5        5

当然,您会收到一些警告,因为“-”无法转换为数字

于 2013-08-23T10:04:16.327 回答
0

前段时间我写了一个小函数来处理在data.frameas中生成某些值NA并使用type.convert来转换输出,就像你使用read.tablena.strings指定的一样。

这是功能:

makemeNA <- function(mydf, NAStrings, fixed = TRUE) {
  dfname <- deparse(substitute(mydf))
  if (!isTRUE(fixed)) {
    mydf <- data.frame(lapply(mydf, function(x) gsub(NAStrings, "", x)))
    NAStrings <- ""
  }
  mydf <- data.frame(lapply(mydf, function(x) type.convert(
    as.character(x), na.strings = NAStrings)))
  mydf
}

在这里它正在使用中:

makemeNA(df, "-")
#    KY27PHY1 KY27PHY2 KY27PHY3
# 1         4        4        5
# 2         5        4        4
# 3         5        4        4
# 4         4        4        4
# 5        NA       NA       NA
# 6         4        5        5
# 7         2        2        1
# 8         3        3        4
# 9         5        5        5
# 10       NA       NA       NA
# 11        4        5        4
# 12        3        3        3
# 13        3        3        3
# 14        5        5        5
# 15        5        5        5

您可以从structure 中看到我们现在有数字输出。

str(makemeNA(df, "-"))
# 'data.frame':  15 obs. of  3 variables:
#  $ KY27PHY1: int  4 5 5 4 NA 4 2 3 5 NA ...
#  $ KY27PHY2: int  4 4 4 4 NA 5 2 3 5 NA ...
#  $ KY27PHY3: int  5 4 4 4 NA 5 1 4 5 NA ...

与 一样na.stringsNAStringsinmakemeNA复数。在这里,我们制作一个破折号并将值“1”放入NA.

str(makemeNA(df, c("-", 1)))
# 'data.frame':  15 obs. of  3 variables:
#  $ KY27PHY1: int  4 5 5 4 NA 4 2 3 5 NA ...
#  $ KY27PHY2: int  4 4 4 4 NA 5 2 3 5 NA ...
#  $ KY27PHY3: int  5 4 4 4 NA 5 NA 4 5 NA ...

您还可以使用正则表达式将值设置为NA,如下所示:

df1 <- data.frame(A = c(1, 2, "-", "not applicable", 5),
                 B = c("not available", 1, 2, 3, 4),
                 C = c("-", letters[1:4]))

将任何带有“not”或“-”的值设为NA

makemeNA(df1, "not.*|-", fixed = FALSE)
#    A  B    C
# 1  1 NA <NA>
# 2  2  1    a
# 3 NA  2    b
# 4 NA  3    c
# 5  5  4    d
str(makemeNA(df1, "not.*|-", fixed = FALSE))
# 'data.frame':  5 obs. of  3 variables:
#  $ A: int  1 2 NA NA 5
#  $ B: int  NA 1 2 3 4
#  $ C: Factor w/ 4 levels "a","b","c","d": NA 1 2 3 4
于 2013-08-23T12:13:40.327 回答
0

您可以使用sapply一次来完成所有操作,但最终会得到 a matrix,因此您必须将其包裹起来as.data.frame才能转换回来。警告只是为了告诉您原始数据中的某些字符无法与数字匹配,因此被替换为NA. 在您的情况下,这些字符是"-". 为确保不打印警告,请使用suppressWarnings

suppressWarnings(as.data.frame(sapply(df,as.numeric)))
   KY27PHY1 KY27PHY2 KY27PHY3
1         4        4        5
2         5        4        4
3         5        4        4
4         4        4        4
5        NA       NA       NA
6         4        5        5
7         2        2        1
8         3        3        4
9         5        5        5
10       NA       NA       NA
11        4        5        4
12        3        3        3
13        3        3        3
14        5        5        5
15        5        5        5
于 2013-08-23T09:35:58.380 回答