向量

笔记

参考

1.《R数据科学》
2. 小洁详解《R数据科学》–第十五章 向量

1.准备工作

library(tidyverse)

2.向量基础

向量的类型主要有两种。

  • 原子向量——c(),其共有6种类型:逻辑型、整型、双精度型、字符型、复数型和原始型。整型和双精度型向量又统称为数值型向量。
  • 列表——list(),有时又称为递归向量,因为列表中也可以包含其他列表。

原子向量与列表之间的主要区别:

  • 原子向量中的各个值都是同种类型的
  • 列表中的各个值可以是不同类型的

在这里插入图片描述

每个向量都有两个关键属性。

  • 类型。可以使用typeof()函数来确定向量的类型:
class(letters)
#[1] "character"
typeof(letters)
#[1] "character"
typeof(1:10)
#[1] "integer"
  • 长度。可以使用length()函数来确定向量的长度:
#对列表做一个尝试,同样的几个元素用c和list分别组合,他们的长度是不同的
x <- c("a", "b", 1:10)
length(x)
#[1] 12
x2 <- list("a", "b", 1:10)
length(x2)
#[1] 3

3.重要的原子向量

4种最重要的原子向量类型是逻辑型、整型、双精度型和字符型。

3.1 逻辑型

只有 3 个可能的取值: FALSE、 TRUE 和 NA。

1:5 %% 2 == 0
# [1] FALSE  TRUE FALSE  TRUE FALSE
a=c(TRUE,FALSE,NA)
a
# [1]  TRUE FALSE    NA

3.2 数值型

整型与双精度型向量统称为数值型向量。
R默认双精度型——如果要创建整数型数值,可以在数字后面加一个 L

typeof(1)#默认是双精度型
#[1] "double"
typeof(1L)#指定为整型
#[1] "integer"

### 整型和双精度型之间的区别
1.双精度型是近似值,双精度型表示的是浮点数,不能由固定数量的内存精确表示。
sqrt(2) ^ 2
# [1] 2
sqrt(2)^2 - 2
# [1] 4.440892e-16

在处理浮点数时,这种现象非常普遍:多数计算都包括一些近似误差。
在比较浮点数时,不能使用==,而应该使用dplyr::near(),这可以容忍一些数据误差。

dplyr::near(sqrt(2)^2,2)
#[1] TRUE

2.特殊值
整形数据有1一个特殊值NA(空值)
双精度型数据有4个特殊值: NA、 NaN(非数字)、 Inf(正无穷) 和 -Inf(负无穷)

C(-1,0,1)/0
#[1]-Inf NaN Inf

不要使用==来检查这些特殊值,而是用is.finite()、 is.infinite() 和is.nan()鉴定这些特殊值类型。

1.is_infinite 判断是否为无限值
> is.infinite(3/0)
#[1] TRUE

2.is_nan -- 判断是否为合法数值
> is.nan(0/0)
#[1] TRUE

3.is_finite 判断是否为有限值
> is.finite(1/9999999999)
#[1] TRUE

在这里插入图片描述

3.3 字符型

R使用的是全局字符串池。
R对每个唯一的字符串只保存一次,节省内存。

3.4 缺失值

每种类型的原子向量都有自己的缺失值:
NA有多种类型

1.逻辑型
NA
#> [1] NA

2.整形
NA_integer_
#> [1] NA

3.双精度型
NA_real_
#> [1] NA

3.字符型
NA_character_
#> [1] NA

4.使用原子向量

如何将一种原子向量转换为另一种,以及何时系统会自动转换。

4.1 强制转换

将一种类型的向量强制转换成另一种类型的方式有两种。

  1. 显式转换
    as.logical()、 as.integer()、 as.double() 、 as.character()、
  2. 隐式转换
    在数值环境中使用逻辑向量,TRUE 转换为 1, FALSE 转换为 0。
    意味着对逻辑向量求和的结果就是其中真值的个数,逻辑向量的均值就是其中真值的比例:
    所以sum成了计数,mean成了比例!
x<-sample(20,100,replace=TRUE)
大于10的数有多少个?
sum(x>18)
# [1] 10
大于10的数的比例是多少?
mean(x>18)
# [1] 0.1

用c()将两种不同类型的元素放到一起,转换为最复杂的元素类型。

x <- c("a", 1.5, 1:10)
typeof(x)
#> [1] "character"
typeof(c(TRUE, 1L))
#> [1] "integer"
typeof(c(1L, 1.5))
#> [1] "double"
typeof(c(1.5, "a"))
#> [1] "character"

原子向量中不能包含不同类型的元素,因为类型是整个向量的一种属性,不是其中单个元素的属性。
如果需要在同一个向量中包含混合类型的元素,那么就需要使用列表。

4.2 检验函数

在这里插入图片描述

4.3 标量与循环规则

向量循环–对向量长度进行强制转换。
R会将较短的向量重复(或称循环)到与较长的向量相同的长度。

> sample(10)+100
 [1] 103 108 106 104 102 101 109 107 110 105
> runif(10)>0.5
 [1] FALSE  TRUE  TRUE  TRUE FALSE FALSE FALSE  TRUE FALSE FALSE

如果两个长度不同的向量相加,R会自动扩展较短的向量,使其与较长的向量一样长,这个过程就称作向量循环

> 1:6 + 1:2
# [1] 2 4 4 6 6 8

除非较长向量的长度不是较短向量长度的整数倍:

1:5 + 1:2
# [1] 2 4 4 6 6
# Warning message:
# In 1:5 + 1:2 :
#   longer object length is not a multiple of shorter object length

向量循环在tibble中则会直接报错,需要手动rep。

rep有两个用法:times和each。默认是times。

tibble(x = 1:4, y = rep(1:2, times = 2))#times不写也一样的。
#> # A tibble: 4 x 2
#>       x     y
#>   <int> <int>
#> 1     1     1
#> 2     2     2
#> 3     3     1
#> 4     4     2
tibble(x = 1:4, y = rep(1:2, each = 2))
#> # A tibble: 4 x 2
#>       x     y
#>   <int> <int>
#> 1     1     1
#> 2     2     1
#> 3     3     2
#> 4     4     2

4.4 向量命名

可以在使用c()函数创建向量时进行命名:
c(x = 1, y = 2, z = 4)
#> x y z 
#> 1 2 4

也可以在向量创建完成后,使用purrr::set_names()函数来命名:

set_names(1:3, c("a", "b", "c"))

#> a b c 
#> 1 2 3

4.5 向量取子集

  1. 按位置提取
x <- c("one", "two", "three", "four", "five")
x[c(3, 2, 5)]#按照位置提取
#> [1] "three" "two"   "five"
x[c(1, 1, 5, 5, 5, 2)]#竟然可以重复
#> [1] "one"  "one"  "five" "five" "five" "two"
x[c(-1, -3, -5)]#除了某几个
#> [1] "two"  "four"
x[c(1, -1)] 不可以正负混合
  1. 用逻辑向量取子集
x <- c(1,NA,5,NA,10)
x[!is.na(x)]#x中的所有非缺失值
# [1]  1  5 10

x[x %% 2 == 0]#偶数和缺失值
# [1] NA NA 10
  1. 按名字取
x=c(a=1,b=2,c=3)
x[c("c","b")]
# c b 
# 3 2 

[ 有一个重要的变体 [[

[[ 从来都是只提取单个元素,并丢弃名称。当想明确表明需要提取单个元素时,就应该使用[[
比如在一个for循环中。[ 和 [[ 的区别对于列表来说更加重要

5.递归向量

可以用list()创建列表

创建原子向量-c()
x <- c(1, 2, 3)
# [1] 1 2 3
创建列表 list()
x <- list(1, 2, 3)
# [[1]]
# [1] 1
# 
# [[2]]
# [1] 2
# 
# [[3]]
# [1] 3

查看列表结构
str(x)
#> List of 3
#>  $ : num 1
#>  $ : num 2
#>  $ : num 3
命名列表
x <- list(a=1,b=2,c=3)
# $a
# [1] 1
# 
# $b
# [1] 2
# 
# $c
# [1] 3

与原子向量不同,list()中可以包含不同类型的对象:

> y<-list("a",1L,1.5,TRUE)
> str(y)

List of 4
 $ : chr "a"
 $ : int 1
 $ : num 1.5
 $ : logi TRUE

列表中还可以多个嵌套列表

> z<-list(list(1,2),list(3,4))
[[1]]
[[1]][[1]]
[1] 1

[[1]][[2]]
[1] 2


[[2]]
[[2]][[1]]
[1] 3

[[2]][[2]]
[1] 4

> str(z)
List of 2
 $ :List of 2
  ..$ : num 1
  ..$ : num 2
 $ :List of 2
  ..$ : num 3
  ..$ : num 4

5.1 列表可视化

x1<-list(c(1,2),c(3,4))
x2<-list(list(1,2),list(3,4))
×3<-list(1,list(2,list(3)))

在这里插入图片描述

5.2 列表取子集

a <- list(a = 1:3, b = "a string", c = pi, d = list(-1, -5))
# $a
# [1] 1 2 3
# 
# $b
# [1] "a string"
# 
# $c
# [1] 3.141593
# 
# $d
# $d[[1]]
# [1] -1
# 
# $d[[2]]
# [1] -5
  1. 用[ 提取子列表
a[1]
# $a
# [1] 1 2 3

a[1:2]
# $a
# [1] 1 2 3
# 
# $b
# [1] "a string"
str(a[1:2])
#> List of 2
#>  $ a: int [1:3] 1 2 3
#>  $ b: chr "a string"
str(a[4])
#> List of 1
#>  $ d:List of 2
#>   ..$ : num -1
#>   ..$ : num -5
  1. [[]] 从列表中提取单个元素。这种方式会从列表中删除一个层次等# 1.准备工作
library(tidyverse)

2.向量基础

向量的类型主要有两种。

  • 原子向量——c(),其共有6种类型:逻辑型、整型、双精度型、字符型、复数型和原始型。整型和双精度型向量又统称为数值型向量。
  • 列表——list(),有时又称为递归向量,因为列表中也可以包含其他列表。

原子向量与列表之间的主要区别:

  • 原子向量中的各个值都是同种类型的
  • 列表中的各个值可以是不同类型的

0

每个向量都有两个关键属性。

  • 类型。可以使用typeof()函数来确定向量的类型:
class(letters)
#[1] "character"
typeof(letters)
#[1] "character"
typeof(1:10)
#[1] "integer"
  • 长度。可以使用length()函数来确定向量的长度:
#对列表做一个尝试,同样的几个元素用c和list分别组合,他们的长度是不同的
x <- c("a", "b", 1:10)
length(x)
#[1] 12
x2 <- list("a", "b", 1:10)
length(x2)
#[1] 3

3.重要的原子向量

4种最重要的原子向量类型是逻辑型、整型、双精度型和字符型。

3.1 逻辑型

只有 3 个可能的取值: FALSE、 TRUE 和 NA。

1:5 %% 2 == 0
# [1] FALSE  TRUE FALSE  TRUE FALSE
a=c(TRUE,FALSE,NA)
a
# [1]  TRUE FALSE    NA

3.2 数值型

整型与双精度型向量统称为数值型向量。
R默认双精度型——如果要创建整数型数值,可以在数字后面加一个 L

typeof(1)#默认是双精度型
#[1] "double"
typeof(1L)#指定为整型
#[1] "integer"

### 整型和双精度型之间的区别
1.双精度型是近似值,双精度型表示的是浮点数,不能由固定数量的内存精确表示。
sqrt(2) ^ 2
# [1] 2
sqrt(2)^2 - 2
# [1] 4.440892e-16

在处理浮点数时,这种现象非常普遍:多数计算都包括一些近似误差。
在比较浮点数时,不能使用==,而应该使用dplyr::near(),这可以容忍一些数据误差。

dplyr::near(sqrt(2)^2,2)
#[1] TRUE

2.特殊值
整形数据有1一个特殊值NA(空值)
双精度型数据有4个特殊值: NA、 NaN(非数字)、 Inf(正无穷) 和 -Inf(负无穷)

C(-1,0,1)/0
#[1]-Inf NaN Inf

不要使用==来检查这些特殊值,而是用is.finite()、 is.infinite() 和is.nan()鉴定这些特殊值类型。

1.is_infinite 判断是否为无限值
> is.infinite(3/0)
#[1] TRUE

2.is_nan -- 判断是否为合法数值
> is.nan(0/0)
#[1] TRUE

3.is_finite 判断是否为有限值
> is.finite(1/9999999999)
#[1] TRUE

1

3.3 字符型

R使用的是全局字符串池。
R对每个唯一的字符串只保存一次,节省内存。

3.4 缺失值

每种类型的原子向量都有自己的缺失值:
NA有多种类型

1.逻辑型
NA
#> [1] NA

2.整形
NA_integer_
#> [1] NA

3.双精度型
NA_real_
#> [1] NA

3.字符型
NA_character_
#> [1] NA

4.使用原子向量

如何将一种原子向量转换为另一种,以及何时系统会自动转换。

4.1 强制转换

将一种类型的向量强制转换成另一种类型的方式有两种。

  1. 显式转换
    as.logical()、 as.integer()、 as.double() 、 as.character()、
  2. 隐式转换
    在数值环境中使用逻辑向量,TRUE 转换为 1, FALSE 转换为 0。
    意味着对逻辑向量求和的结果就是其中真值的个数,逻辑向量的均值就是其中真值的比例:
    所以sum成了计数,mean成了比例!
x<-sample(20,100,replace=TRUE)
大于10的数有多少个?
sum(x>18)
# [1] 10
大于10的数的比例是多少?
mean(x>18)
# [1] 0.1

用c()将两种不同类型的元素放到一起,转换为最复杂的元素类型。

x <- c("a", 1.5, 1:10)
typeof(x)
#> [1] "character"
typeof(c(TRUE, 1L))
#> [1] "integer"
typeof(c(1L, 1.5))
#> [1] "double"
typeof(c(1.5, "a"))
#> [1] "character"

原子向量中不能包含不同类型的元素,因为类型是整个向量的一种属性,不是其中单个元素的属性。
如果需要在同一个向量中包含混合类型的元素,那么就需要使用列表。

4.2 检验函数

2

4.3 标量与循环规则

向量循环–对向量长度进行强制转换。
R会将较短的向量重复(或称循环)到与较长的向量相同的长度。

> sample(10)+100
 [1] 103 108 106 104 102 101 109 107 110 105
> runif(10)>0.5
 [1] FALSE  TRUE  TRUE  TRUE FALSE FALSE FALSE  TRUE FALSE FALSE

如果两个长度不同的向量相加,R会自动扩展较短的向量,使其与较长的向量一样长,这个过程就称作向量循环

> 1:6 + 1:2
# [1] 2 4 4 6 6 8

除非较长向量的长度不是较短向量长度的整数倍:

> 1:5 + 1:2

# [1] 2 4 4 6 6
# Warning message:
# In 1:5 + 1:2 :
#   longer object length is not a multiple of shorter object length

向量循环在tibble中则会直接报错,需要手动rep。

rep有两个用法:times和each。默认是times。

tibble(x = 1:4, y = rep(1:2, times = 2))#times不写也一样的。
#> # A tibble: 4 x 2
#>       x     y
#>   <int> <int>
#> 1     1     1
#> 2     2     2
#> 3     3     1
#> 4     4     2
tibble(x = 1:4, y = rep(1:2, each = 2))
#> # A tibble: 4 x 2
#>       x     y
#>   <int> <int>
#> 1     1     1
#> 2     2     1
#> 3     3     2
#> 4     4     2

4.4 向量命名

可以在使用c()函数创建向量时进行命名:
c(x = 1, y = 2, z = 4)
#> x y z 
#> 1 2 4

也可以在向量创建完成后,使用purrr::set_names()函数来命名:

set_names(1:3, c("a", "b", "c"))

#> a b c 
#> 1 2 3

4.5 向量取子集

  1. 按位置提取
x <- c("one", "two", "three", "four", "five")
x[c(3, 2, 5)]#按照位置提取
#> [1] "three" "two"   "five"
x[c(1, 1, 5, 5, 5, 2)]#竟然可以重复
#> [1] "one"  "one"  "five" "five" "five" "two"
x[c(-1, -3, -5)]#除了某几个
#> [1] "two"  "four"
x[c(1, -1)] 不可以正负混合
  1. 用逻辑向量取子集
x <- c(1,NA,5,NA,10)
x[!is.na(x)]#x中的所有非缺失值
# [1]  1  5 10

x[x %% 2 == 0]#偶数和缺失值
# [1] NA NA 10

3.按名字取

x=c(a=1,b=2,c=3)
x[c("c","b")]
# c b 
# 3 2 

[ 有一个重要的变体[[。

[[从来都是只提取单个元素,并丢弃名称。当想明确表明需要提取单个元素时,就应该使用[[
比如在一个for循环中。[和[[的区别对于列表来说更加重要

5.递归向量

可以用list()创建列表

创建原子向量-c()
x <- c(1, 2, 3)
# [1] 1 2 3
创建列表 list()
x <- list(1, 2, 3)
# [[1]]
# [1] 1
# 
# [[2]]
# [1] 2
# 
# [[3]]
# [1] 3

查看列表结构
str(x)
#> List of 3
#>  $ : num 1
#>  $ : num 2
#>  $ : num 3
命名列表
x <- list(a=1,b=2,c=3)
# $a
# [1] 1
# 
# $b
# [1] 2
# 
# $c
# [1] 3

与原子向量不同,list()中可以包含不同类型的对象:

> y<-list("a",1L,1.5,TRUE)
> str(y)

List of 4
 $ : chr "a"
 $ : int 1
 $ : num 1.5
 $ : logi TRUE

列表中还可以多个嵌套列表

> z<-list(list(1,2),list(3,4))
[[1]]
[[1]][[1]]
[1] 1

[[1]][[2]]
[1] 2


[[2]]
[[2]][[1]]
[1] 3

[[2]][[2]]
[1] 4

> str(z)
List of 2
 $ :List of 2
  ..$ : num 1
  ..$ : num 2
 $ :List of 2
  ..$ : num 3
  ..$ : num 4

5.1 列表可视化

x1<-list(c(1,2),c(3,4))
x2<-list(list(1,2),list(3,4))
×3<-list(1,list(2,list(3)))

3

5.2 列表取子集

a <- list(a = 1:3, b = "a string", c = pi, d = list(-1, -5))
# $a
# [1] 1 2 3
# 
# $b
# [1] "a string"
# 
# $c
# [1] 3.141593
# 
# $d
# $d[[1]]
# [1] -1
# 
# $d[[2]]
# [1] -5
  1. [] 提取子列表
a[1]
# $a
# [1] 1 2 3

a[1:2]
# $a
# [1] 1 2 3
# 
# $b
# [1] "a string"
str(a[1:2])
#> List of 2
#>  $ a: int [1:3] 1 2 3
#>  $ b: chr "a string"
str(a[4])
#> List of 1
#>  $ d:List of 2
#>   ..$ : num -1
#>   ..$ : num -5
  1. [[]] 从列表中提取单个元素。这种方式会从列表中删除一个层次等级
> a[1]
# $a
# [1] 1 2 3
> a[[3]]
# [1] 3.141593
> a["c"]
# $c
# [1] 3.141593
> a[["c"]]
# [1] 3.141593

或者 $ 提取元素

a$c
# [1] 3.141593

[ 和 [[ 之间的区别非常重要,但二者很容易混淆

对于列表来说,[和[[之间的区别是非常重要的,因为[[会使列表降低一个层级,而
[则会返回一个新的、更小的列表。

记住 [[]] 会降低层级!!!

[[]][[]] 这个层级中里面的元素

4

6 特性

任何向量都可以通过其特性来附加任意元数据。
可以将特性看作可以附加在任何对象上的一个向量命名列表
可以使用attr()函数来读取和设置单个特性值,也可以使用attributes()函数同时查看所有特性值:

x <- 1:10
attr(x, "greeting") <- "Hi!"
attr(x, "farewell") <- "Bye!"
attributes(x)
#$greeting
#[1] "Hi!"
#> 
#$farewell
#[1] "Bye!"
  • 名称:用于命名向量元素。
  • 维度:使得向量可以像矩阵或数组那样操作。
  • 类:用于实现面向对象的S3系统。
y <- c(1,3,5)
attr(y,"names") <- c("a","b","c")
y
#a b c 
#1 3 5

这就是命名操作,和之前讲的效果一样
set_names(c(1,3,5),c("a","b","c"))
#a b c 
#1 3 5

7.扩展向量

(1)因子

x <- factor(c("ab", "cd", "ab"), levels = c("ab", "cd", "ef"))
typeof(x)
#[1] "integer"
class(x) 
#[1] "factor"
attributes(x)#不仅能展示levels还能展示class
#$levels
#[1] "ab" "cd" "ef"
# 
#$class
#[1] "factor"

(2)tibble
tibble 是扩展的列表,有 3 个class: tbl_df、 tbl 和 data.frame。它的特性有 2 个:(列)
names 和 row.names。

tb <- tibble::tibble(x = 1:5, y = 5:1)
typeof(tb)
#> [1] "list"
> a[1]
# $a
# [1] 1 2 3
> a[[3]]
# [1] 3.141593
> a["c"]
# $c
# [1] 3.141593
> a[["c"]]
# [1] 3.141593

级或者 $ 提取元素

a$c
# [1] 3.141593

== [ 和 [[ 之间的区别非常重要,但二者很容易混淆==

对于列表来说,[和[[之间的区别是非常重要的,因为[[会使列表降低一个层级,而
[则会返回一个新的、更小的列表。

记住 [[]] 会降低层级!!!

[[]][[]] 这个层级中里面的元素

在这里插入图片描述

6 特性

任何向量都可以通过其特性来附加任意元数据。
可以将特性看作可以附加在任何对象上的一个向量命名列表
可以使用attr()函数来读取和设置单个特性值,也可以使用attributes()函数同时查看所有特性值:

x <- 1:10
attr(x, "greeting") <- "Hi!"
attr(x, "farewell") <- "Bye!"
attributes(x)
#$greeting
#[1] "Hi!"
#> 
#$farewell
#[1] "Bye!"
  • 名称:用于命名向量元素。
  • 维度:使得向量可以像矩阵或数组那样操作。
  • 类:用于实现面向对象的S3系统。
y <- c(1,3,5)
attr(y,"names") <- c("a","b","c")
y
#a b c 
#1 3 5

这就是命名操作,和之前讲的效果一样
set_names(c(1,3,5),c("a","b","c"))
#a b c 
#1 3 5

7.扩展向量

(1)因子

x <- factor(c("ab", "cd", "ab"), levels = c("ab", "cd", "ef"))
typeof(x)
#[1] "integer"
class(x) 
#[1] "factor"
attributes(x)#不仅能展示levels还能展示class
#$levels
#[1] "ab" "cd" "ef"
# 
#$class
#[1] "factor"

(2)tibble
tibble 是扩展的列表,有 3 个class: tbl_df、 tbl 和 data.frame。它的特性有 2 个:(列)
names 和 row.names。

tb <- tibble::tibble(x = 1:5, y = 5:1)
typeof(tb)
#> [1] "list"
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值