0%

R语言中常见的特殊值、数据类型和相关方法

R中常见的特殊值:

  • NA:缺失数据,另外NA其实对于每种原子向量都有一种自己的缺失值。
  • NaN:无意义的数,比如sqrt(-2), 0/0。
  • Inf:正无穷大
  • -Inf:负无穷大
  • NULL:不存在,通过is.na()等方法不会返回任何信息

特殊值相关方法:

特殊值不能通过==进行比较,而应该使用以下的方法。

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

示例

1
2
3
4
5
(x<-c(0/1, 0/0, 1/0, NA, NULL))
is.na(x)
is.nan(x)
is.finite(x)
is.infinite(x)

Output:

intput 0/1 0/0 1/0 NA NULL
output 0 NaN Inf <NA>
is.na(x) FALSE TRUE FALSE TRUE
is.nan(x) FALSE TRUE FALSE FALSE
is.finite(x) TRUE FALSE FALSE FALSE
is.infinite(x) FALSE FALSE TRUE FALSE

NULL 什么也不会输出。

一个值得注意的是NA 和NaN的区别,在前面说到了,NA是缺失的数据,而NaN是没有意义的数字,我们可以认为没有意义数据填充也是某种程度上的缺失。但是缺失的数据没有意义吗?不是这样的。

另一个要注意的是 1/01/0s是Inf而不是NAN。


对于Na、NaN这些特殊值,有很多trick,看一下这个问题:

Why is x[-which(x > 0)] not the same as x[x <= 0]?

数据类型

R中的数据类型十分令人迷惑。主要的类型如下所示:

  • vector
  • dataframe
  • matrix
  • list

下面来说说我踩到的一些坑。

道生1,1生2,2生Vector,Vector生万物

最开始我以为类型是某种并列的关系,比如vector就是类似于C中的数组和python中元组的某种诡异结合体,matrix就是二维数组,但是事实并没有这么简单……很快就会发现一些问题,比如:

1
2
3
4
5
6
7
8
x = list(1,2,3,4)
y = c(1,2,3,4)
typeof(x)
typeof(y)
x= as.vector(x)
y = as.list(y)
typeof(x)
typeof(y)

输出是:

1
2
3
4
'list'
'double'
'list'
'list'

这就很诡异 ,你问R 说y的类型是什么,然后它告诉你是双精度而不是期待的“Vector”。并且当你把list尝试强制转化成vector时,又会告诉你它还是个list。

这就是第一个trick:

R中的向量实际上是两种类型:

  • 原子向量(atomic vector): 包括逻辑型、整型、双精度型(数值型)、字符型、复数型和原始型。
  • 列表,也叫做递归向量,因为列表中可以包含其他的列表

有如下设定:

  1. 原子向量中的各个值一定是同种类型的,而列表中的各个值可以是不同类型的。
  2. 双精度型的原子向量总是存在一些近似误差而不能直接比较,可以用dplyr::near()
  3. R-base 中的is.vector() is.atomic()这样的函数经常返回“出人意料的结果”,解决的办法是用purrr中的is_*函数(居然没有人尝试着解决一下这些问题?????

在原子向量的基础上,可以构建出拓展向量。如:

  • 因子
  • 日期和日期时间
  • tibble(包括data.frame)

对于之前提到的matrixdata.frame:

1
2
3
4
5
x <- data.frame("SN" = 1:2, "Age" = c(21,15), "Name" = c("John", "Dora"))
is.vector(x)
typeof(x)
y <- matrix(c(1,2,3))
typeof(y)

输出是:

1
2
3
FALSE
'list'
'double'

typeof的结果看,matrixdata.frame也是向量。

那么为什么is.vector()会返回false呢?

is.vector() does not test if an object is a vector. Instead it returns TRUE only if the object is a vector with no attributes apart from names.

is.vector()方法判断的并不是变量是不是向量。正如上面所说:他们会返回“出乎意料的结果”。

惊不惊喜,意不意外?