基础
广义来说,向量有三种类型:
- 存储相同数据类型的atomic vector;
- 不同类型的 list。
- NULL,长度为零的vector。
属性(attributes):
- 纬度,二维的矩阵,多维的array;
- 类型 class,专门用于S3 类对象的构造。
image.png
向量分类
常见的有四种:
- 特别的书写规范:
image.png
- 处理NA 值的注意事项:
image.png
除此之外,还有两种不常见的:参见:https://www.cnblogs.com/mfrank/p/14051513.html
属性
一共有三种获得的函数:
代码语言:javascript复制a <- 1:3
attr(a, "x") <- "abcdef"
attr(a, "x")
#> [1] "abcdef"
attr(a, "y") <- 4:6
str(attributes(a))
#> List of 2
#> $ x: chr "abcdef"
#> $ y: int [1:3] 4 5 6
# Or equivalently
a <- structure(
1:3,
x = "abcdef",
y = 4:6
)
str(attributes(a))
#> List of 2
#> $ x: chr "abcdef"
#> $ y: int [1:3] 4 5 6
attributes 可以批量获取对象所有的属性;structure 可以批量定义对象所有的属性。
此外属性一般也是短暂形成的:
只有names, 和dim 属性会被继承(说继承可能不太严谨,但你大概明白我的意思吧~):
代码语言:javascript复制> b <- matrix(1:4, ncol=2)
> b
[,1] [,2]
[1,] 1 3
[2,] 2 4
> attributes(b)
$dim
[1] 2 2
> names(b) <- 3
> b
[,1] [,2]
[1,] 1 3
[2,] 2 4
attr(,"names")
[1] "3" NA NA NA
> b[q]
Error in b[q] : invalid subscript type 'closure'
> b[1]
3
1
> b[2]
<NA>
2
> attributes(b[2])
$names
[1] NA
- 创建带名字的向量的三种方式:
如果名称中有确实值的话:
- 获取向量、矩阵、array 信息的函数异同:
image.png
S3 类向量
一个对象,一旦有了class 属性,则其会变为S3 类型对象:
代码语言:javascript复制> x1
[1] 3
>
> otype(x1)
[1] "base"
> attr(x1, "class") <- "good"
> otype(x1)
[1] "S3"
> attributes(x1)
$class
[1] "good"
其实我们通常使用的因子类型,也是S3 对象,此外还有:
因子
- 因子是基于整型向量改写的S3 对象,而许多的因子实际上由字符串转换而来的:
> x3
[1] a b
Levels: a b
> mode(x3)
[1] "numeric"
> x4 <- gsub("a", "aa", x3)
> x4
[1] "aa" "b"
> mode(x4)
[1] "character"
这也是为什么我们如果用c() 连接因子,会得到数字:
因为实际使用的是factor 背后的integer 值。
代码语言:javascript复制> x3
[1] a b
Levels: a b
> x2
[1] 1 2 3
Levels: 1 2 3
> c(x2,x3)
[1] 1 2 3 1 2
因此,如果需要转换因子,最好的方法是显式修改;如果需要避免factor 转型,则等向量一切处理完毕后,在转换为因子。
另外,在处理因子的时候还需要谨慎levels 属性。我们在将向量转为因子时,可以使用默认顺序下的levels 或手动设定,此时向量本身顺序并不会改变;但如果对已创建的因子转换levels,则因子本身顺序也会按照levels 的顺序改变。
因子取子集,去除其他不包含levels的方法:
其他
- 日期
image.png
- 日期-时间
image.png
- 时间段
反映的是两段时间的差值:
列表
从大类上,list 是区别于atomic 的另一大类向量。
最大的区别在于,list 可以存储不同类型的数据。
list 也可以有自己的多维矩阵:
从输出结果来看,它与atomic 创建的矩阵无二,但本质来说,其是不同的。atomic 的矩阵如果将元素修改与整体类型不同,则会强迫转型。
数据框
- 识别非法名称
image.png
- tibble
可以使用运算符号创建
- 为什么要窄长的ggplot 类型数据,不要长宽数据
转换rownames 的方法:
- 数据框中定义列表的方法
- 数据框中定义矩阵与数据框的方法
个人感觉如果存放复杂的或多个纬度的数据,使用tibble会好一点:
代码语言:javascript复制> dfm <- data.frame(
x = 1:3 * 10
)
> dfm$y <- matrix(1:9, nrow = 3)
> dfm$z <- data.frame(a = 3:1, b = letters[1:3], stringsAsFactors = FALSE)
> dfm <- data.frame(
x = 1:3 * 10
)
> dfm$y <- matrix(1:9, nrow = 3)
> dfm$z <- data.frame(a = 3:1, b = letters[1:3], stringsAsFactors = FALSE)
> dfm
x y.1 y.2 y.3 z.a z.b
1 10 1 4 7 3 a
2 20 2 5 8 2 b
3 30 3 6 9 1 c
> dfm$y.1
NULL
# 这里y 矩阵的三个维度会被强制命名后缀增加.1,.2,.3
> tibble::as_tibble(dfm)
# A tibble: 3 x 3
x y[,1] [,2] [,3] z$a $b
<dbl> <int> <int> <int> <int> <chr>
1 10 1 4 7 3 a
2 20 2 5 8 2 b
3 30 3 6 9 1 c
data.frame 太容易让人confusing !