G. B.

个人博客

且将新火试新茶,诗酒趁年华


数据结构

数据结构

向量

向量包含atomic vector和list,它们有三个共同性质属性:

  • 类型 typeof()
  • 长度 length()
  • 属性 attributes(),附加的任意元数据

###

原子向量atomic vector包含:

  • logical
  • integer
  • double 即 numeric
  • character
  • complex 复合型
  • raw 原始型

其中后两者属于罕见类型

###

原子向量使用c()来创建,在c()中使用NANA会自动被转换成正确的数据类型,NA有以下几种类型:

  • NA_real_
  • NA_integer_
  • NA_character_

###

is.numeric()通常用来判断向量的“数值性”,无论是整型还是双精度型向量都返回TRUE。所以如果需要精确的判断,还是要用is.integeris.double

###

atomic vector中的每个元素都必须具有相同的类型,所以如果把不同的数据结合成一个向量,他们会被强制转换成最具有灵活性的数据类型。数据类型的灵活性排序为:character > double > integer > logical

###

不要使用is.vector()来判断一个对象是否是向量,只有在对象是向量且除了名字之外没有其他属性的情况下它才返回TRUE,前面定义了向量的概念,所以判断向量应该用 is.atomic() || is.list()

###

列表使用list()来创建,有时被称作递归(recursive)向量,因为一个列表可以包含其他列表

x <- list(list(list(list())))
str(x)
#List of 1
# $ :List of 1
#  ..$ :List of 1
#  .. ..$ : list()

###

c()可以将多个列表结合在一起,但如果把原子向量和列表放在一起,c()会强制把原子向量转换成列表

x <- list(list(1,2),c(3,4))
y <- c(list(1,2),c(3,4))
str(x)
#List of 2
# $ :List of 2
#  ..$ : num 1
#  ..$ : num 2
# $ : num [1:2] 3 4
str(y)
#List of 4
# $ : num 1
# $ : num 2
# $ : num 3
# $ : num 4

属性

###

attr()可以单独访问对象的一个属性,attributes()可以同时访问所有属性

y <- 1:10
attr(y,"my_attributes") <- "This is a vector"
structure(1:10,my_attributes = "This is a vector")

两种方式是相同效果的。

###

默认情况下向量被修改后它的大多数属性都会丢失,除了以下三个:

  • name
  • dimension
  • class

这三个属性都使用各自专门的存取函数,而不能用attr()来做操作,可以使用uname()来删除向量的名称

###

因子factor是只能包含预先定义值的向量,因子建立在整型向量的基础上,只有两个属性class()levels()

###

进行读取文件操作时,一个很好用的配置项stringsAsFactors = FALSE,避免了默认设置下字符串向量被转换成因子向量(挺烦人的)。

###

structure(1:5,comment = "my attribute")
#> [1] 1 2 3 4 5

没有显示属性的原因是comment属性是一个特殊的属性,它默认不输出,是隐式保存的,只能用attributes()comment()来调取

###

f1 <- factor(letters)
levels(f1) <- rev(levels(f1))  # 整个f1对象被倒序了
f2 <- rev(factor(letters))  # 只有数值被倒序了,levels没有
f3 <- factor(letters,levels = rev(letters))  # 只有levels被倒序了

矩阵和数据框

###

使用plyr::rbind.fill(),如果合并数据框时两个数据框列数不同,则将没有的列以NA填充

###

数据框实际上是一个向量列表,所以数据框可能有某一列是list

df <- data.frame(x=1:3)
df$y <- list(1:2,1:3,1:4)
# 也可以写成
df <- data.frame(x=1:3,y=I(list(1:2,1:3,1:4)))
#> str(df)
#>'data.frame':	3 obs. of  2 variables:
#> $ x: int  1 2 3
#> $ y:List of 3
#>  ..$ : int  1 2
#>  ..$ : int  1 2 3
#>  ..$ : int  1 2 3 4

同理数据框的某一列也可以是matrix或array,只要生成时用I()包裹即可,但应该小心,很多函数默认数据框的每一列都是atomic vector