3.5 检查和更改类

直接在命令提示符下,以交互的方式键入类class的函数名来检查变量是很有用的。但是如果想在脚本中测试对象的类型,则最好用is函数,或针对某个类写的特定函数。通常,我们会做这样的测试:

  1. if(!is(x, "some_class"))
  2. {
  3. # 采取某些纠正措施
  4. }

大部分的类都会有自己的is.*函数。通常,直接调用它们比使用通用is函数稍显高效。例如:

  1. is.character("red lorry, yellow lorry")
  2. ## [1] TRUE
  3. is.logical(FALSE)
  4. ## [1] TRUE
  5. is.list(list(a = 1, b = 2))
  6. ## [1] TRUE

以下命令可查看在base包中所有的is函数:

  1. ls(pattern = "^is", baseenv())
  2. ## [1] "is.array" "is.atomic"
  3. ## [3] "is.call" "is.character"
  4. ## [5] "is.complex" "is.data.frame"
  5. ## [7] "is.double" "is.element"
  6. ## [9] "is.environment" "is.expression"
  7. ## [11] "is.factor" "is.finite"
  8. ## [13] "is.function" "is.infinite"
  9. ## [15] "is.integer" "is.language"
  10. ## [17] "is.list" "is.loaded"
  11. ## [19] "is.logical" "is.matrix"
  12. ## [21] "is.na" "is.na.data.frame"
  13. ## [23] "is.na.numeric_version" "is.na.POSIXlt"
  14. ## [25] "is.na<-" "is.na<-.default"
  15. ## [27] "is.na<-.factor" "is.name"
  16. ## [29] "is.nan" "is.null"
  17. ## [31] "is.numeric" "is.numeric.Date"
  18. ## [33] "is.numeric.difftime" "is.numeric.POSIXt"
  19. ## [35] "is.numeric_version" "is.object"
  20. ## [37] "is.ordered" "is.package_version"
  21. ## [39] "is.pairlist" "is.primitive"
  22. ## [41] "is.qr" "is.R"
  23. ## [43] "is.raw" "is.recursive"
  24. ## [45] "is.single" "is.symbol"
  25. ## [47] "is.table" "is.unsorted"
  26. ## [49] "is.vector" "isatty"
  27. ## [51] "isBaseNamespace" "isdebugged"
  28. ## [53] "isIncomplete" "isNamespace"
  29. ## [55] "isOpen" "isRestart"
  30. ## [57] "isS4" "isSeekable"
  31. ## [59] "isSymmetric" "isSymmetric.matrix"
  32. ## [61] "isTRUE"

在上例中,ls列出所有的变量名,"^is"是一个正则表达式,它意味着“匹配所有以'is'开头的字符串”,而baseenv函数则返回base包中所有的环境。环境是相对高级的话题,将在第6章讨论,现在不用拘泥于它的含义。

assertive包3含有更多is函数,命名方式更加一致。

3 这个包是我写的。

有点奇怪的是,is.numeric函数对整数和浮点数都返回TRUE值。如果我们只测试浮点数,则须使用is.double。然而,一般无需这么做,因为在R中浮点和整数几乎能互换使用。请注意,在下例中,在数字后面添加L后缀就能把它转换为整数:

  1. is.numeric(1)
  2. ## [1] TRUE
  3. is.numeric(1L)
  4. ## [1] TRUE
  5. is.integer(1)
  6. ## [1] FALSE
  7. is.integer(1L)
  8. ## [1] TRUE
  9. is.double(1)
  10. ## [1] TRUE
  11. is.double(1L)
  12. ## [1] FALSE

有时候,我们想改变一个对象的类型。这就是所谓的转型(casting),大部分的is*函数都有与之对应的as*函数。尽可能使用特定的as*函数而非单纯的as函数,因为它们通常更有效,而且往往针对该类会有额外的逻辑。例如,当尝试把字符串转换为数字时,as.numeric比单独的as函数效率稍高,虽然两者皆可使用:

  1. x <- "123.456"
  2. as(x, "numeric")
  3. ## [1] 123.5
  4. as.numeric(x)
  5. ## [1] 123.5

注意

R能打印到小数点后第几位取决于R的设置。你可以使用options(digits=n)来设置全局默认选项,其中n在1和22之间。第7章将再讨论如何控制打印数字。

然而,请注意在下例中,当一个向量被转换成一个数据框时(类似电子表格的数据变量),as函数抛出一个错误:

  1. y <- c(2, 12, 343, 34997) #请参考 http://oeis.org/A192892
  2. as(y, "data.frame")
  3. as.data.frame(y)

注意

一般情况下,特定类的变量的使用应始终优先于标准函数as

尽管不推荐(见16.7节,类的分配另有用途),我们也可以直接给对象分配一个新的类以改变其类型:

  1. x <- "123.456"
  2. class(x) <- "numeric"
  3. x
  4. ## [1] 123.5
  5. is.numeric(x)
  6. ## [1] TRUE