从程序语言的角度来看,R 中的数据或对象的结构比较混杂。 但从数值统计和计算的实用角度来看又觉得十分方便。

首先,单个的数据体的类型,或者说是 R 的基本数据类型, 是在 R 中构成更加复杂数据结构的数据表示, 也是数据的基本存储类型,有

  • logical 逻辑
  • integer 整数
  • double 浮点数
  • complex 复数
  • character 字符串
  • raw 字节串
  • list 列表
  • NULL 空
  • … 还有很多其它的类型

其中的 integer 和 double 又统称为 numeric(数值型), 在 R 中使用时常常不加区分,并且在显示时有向 integer 靠拢的趋势。 使用 is.numeric(x) 来判断一份数据是否为 numeric。 使用 as.numeric(x) 来把一份数据转换成 numeric。

注意在R中,NULL(空)是一种特殊的数据类型,这个不仅仅是数值类型就有, 几乎适用于所有类型,实际上就是空指针,是内存中的空地址, 可以理解成“没有”。 使用 is.null(x) 来判断一份数据是否为 NULL。 使用 as.null(x) 来把一份数据转换成 NULL,实际上就是不对内存进行复制或引用。

另外,在 R 中使用数据进行运算时,常常隐含地 存在一种内在的数据类型转换机制,叫作 coerce。 如果按字面理解则为“强制类型转换”,但实际上这种“强制”是事先约定好的, 在真正使用时常常无需特别指明,所以对于使用者来说,感觉是“隐含”的。

在对数据类型进行转换时,使用 as() 函数。例如把逻辑类型转换成整数类型:

> as.integer(TRUE)
[1] 1
> as.integer(FALSE)
[1] 0
>

又例如把数值转换成逻辑类型:

> as.logical(0)
[1] FALSE
> as.logical(1)
[1] TRUE
> as.logical(-0.00001)
[1] TRUE
> as.logical(Inf)
[1] TRUE
>

凡非零的有效数值都会被转换成 TRUE,而只有零被转换成 FALSE。

对于数值类型,还有几个特殊的值:

  • NaN 非数值,无法表达成数值,一般用来表示没有数值,或者缺少数据;
  • Inf 无穷大,不分阶地,超出表达范围的大于零的某个数值;
  • -Inf 负无穷大,不分阶地,超出表达范围的小于零的某个数值。

测试一个数值或数据是否是以上的特殊值,可以分别使用:

  • is.finite(x)
  • is.infinite(x)
  • is.nan(x)

使用 typeof()、mode()、class()等来获得一个数据的类型信息。例如:

> typeof(10)
[1] "double"
> mode(10)
[1] "numeric"
> class(10)
[1] "numeric"
> str(10)
 num 10
> typeof(1:10)
[1] "integer"
> mode(1:10)
[1] "numeric"
> class(1:10)
[1] "integer"
> str(1:10)
 int [1:10] 1 2 3 4 5 6 7 8 9 10
>

typeof() 和 mode() 是从数据的存储角度来看待数据内容的,它们的细微区别 是历史因素造成的,可能程序员会更加关心它们两者的区别, R 是从 S 语言演变过来的,在 R 中提倡使用 typeof(), 而如果想要兼营 S 语言则应该使用 mode() 。

而 class() 是定义和标识一个对象应该被看成是什么类型的, 主要是从操作的角度来看待的, 也就是应该使用一组什么类型相关的操作或者方法来处理这个数据。 自然地,如果实际存储的类型与所定义或标识的类型不一样, 也就会有隐含的类型转换。

参见 stackexchange: Mode, Class and Type of R objects

> x<-list("a",c(1,2))

> # x is a list
> class(x)
[1] "list"
> # class can be user defined
> class(x)<-"newclass"
> class(x)
[1] "newclass"

> typeof(x)
[1] "list"
# you cannot assign a different type using typeof()
> typeof(x)<-"newclass"
Error in typeof(x) <- "newclass" : could not find function "typeof<-"