数据结构
向量
向量包含atomic vector和list,它们有三个共同性质属性:
- 类型
typeof()
- 长度
length()
- 属性
attributes()
,附加的任意元数据
###
原子向量atomic vector包含:
- logical
- integer
- double 即 numeric
- character
- complex 复合型
- raw 原始型
其中后两者属于罕见类型
###
原子向量使用c()
来创建,在c()
中使用NA
,NA
会自动被转换成正确的数据类型,NA
有以下几种类型:
NA_real_
NA_integer_
NA_character_
###
is.numeric()
通常用来判断向量的“数值性”,无论是整型还是双精度型向量都返回TRUE。所以如果需要精确的判断,还是要用is.integer
或is.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