R数据格式与apply函数

R数据格式与apply函数

sample(11:16,4,replace = T)
[1] 14 13 15 14
sample(11:16,4,replace = T)
[1] 11 12 15 14
sample(11:16,4,replace = T)
[1] 15 16 16 12

apply系列函数的基本作用是对数组(array,可以是多维)或者列表(list)按照元素或元素构成的子集合进行迭代,并将当前元素或子集合作为参数调用某个指定函数。vector是一维的array,dataframe可以看作特殊的list。

一、矩阵(matrix)

我们可以把矩阵看作:向量+维度属性,这个维度是一个整数向量,只包含两个元素行数和列数,分别用nrow和ncol表示。

x<-matrix(nrow=3,ncol=2)
x
[,1] [,2]
[1,] NA NA
[2,] NA NA
[3,] NA NA

x<-matrix(1:6,nrow=3,ncol=2)
x
[,1] [,2]
[1,] 1 4
[2,] 2 5
[3,] 3 6

dim(x)
[1] 3 2

2、用向量+维度属性创建矩阵

y<-1:6
dim(y)<-c(2,3)
y
[,1] [,2] [,3]
[1,] 1 3 5
[2,] 2 4 6

3、拼接矩阵

y<-1:6
dim(y)<-c(2,3)
y
[,1] [,2] [,3]
[1,] 1 3 5
[2,] 2 4 6
y2<-matrix(1:6,nrow=2,ncol=3)
y2
[,1] [,2] [,3]
[1,] 1 3 5
[2,] 2 4 6
rbind(y,y2)
[,1] [,2] [,3]
[1,] 1 3 5
[2,] 2 4 6
[3,] 1 3 5
[4,] 2 4 6
矩阵y和y2都是2行3列的矩阵,那么按行拼接就是4行3列的矩阵。

二、数组(array)

数组与矩阵类似,但是数组的维度可以大于2。

1、用array()函数创建2维数组

x<-array(1:24,dim=c(4,6))
x
[,1] [,2] [,3] [,4] [,5] [,6]
[1,] 1 5 9 13 17 21
[2,] 2 6 10 14 18 22
[3,] 3 7 11 15 19 23
[4,] 4 8 12 16 20 24

2、用array()函数创建3维数组

x1<-array(1:24,dim=c(2,3,4))
x1
, , 1

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

[1,] 1 3 5
[2,] 2 4 6

, , 2

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

[1,] 7 9 11
[2,] 8 10 12

, , 3

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

[1,] 13 15 17
[2,] 14 16 18

, , 4

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

[1,] 19 21 23
[2,] 20 22 24

, ,1代表第3个维度里的第1个元素,我们可以看到第3个维度共有4个元素,第3个维度里的第1个元素是一个2行3列的矩阵,4代表有这样4个2行3列的矩阵。

dim(x1)
[1] 2 3 4
dim(x1)[1]
[1] 2
dim(x1)[2]
[1] 3
dim(x1)[3]
[1] 4
x1[1,]
[,1] [,2] [,3] [,4]
[1,] 1 7 13 19
[2,] 3 9 15 21
[3,] 5 11 17 23

取每个维度的第一行!!!!

sum(x1[1,])
[1] 144

sum(x1[1,])
[1] 144
sum(x1[2,])
[1] 156

apply系列函数这些函数间的关系

作用目标 在每个元素上应用 在子集合上应用
array apply tapply
list lapply (…) by

apply(array, margin, FUN, …)
在array上,沿margin方向,依次调用 FUN 。返回值为vector。margin表示数组引用的第几维下标(即array[index1, index2, …]中的第几个index),1对应为1表示行,2表示列,c(1,2)表示行列。margin=1时, apply(a, 1, sum) 等效于下面的操作

result<-c()
result
NULL
a[1,]
[,1] [,2] [,3] [,4]
[1,] 1 7 13 19
[2,] 3 9 15 21
[3,] 5 11 17 23
result <- c(result, sum(a[1,]))
result
[1] 144
result <- c(result, sum(a[2,]))
result
[1] 144 156
result=c()
for (i in c(1:dim(a)[1])) { result <- c(result, sum(a[i,]))

  • }

result
[1] 144 156

经实测,只能用在二维及以上的array上,不能用在vector上(如果要应用于vector,请使用 lapply 或 sapply )。以matrix为例,如下

m <- matrix(c(1:10), nrow=2)
m
[,1] [,2] [,3] [,4] [,5]
[1,] 1 3 5 7 9
[2,] 2 4 6 8 10
apply(m, 1, sum)
[1] 25 30
apply(m, 2, sum)
[1] 3 7 11 15 19
1对应为1表示行,2表示列,c(1,2)表示行列。

tapply(array, indices, margin, FUN=NULL, …)
按 indices 中的值分组,把相同值对应下标的array中的元素形成一个集合,应用到 FUN 。类似于group by indices的操作。如果 FUN 返回的是一个值, tapply 返回vector;若 FUN 返回多个值, tapply 返回list

当 FUN 为 NULL 的时候,返回一个长度和array中元素个数相等的vector,指示分组的结果,vector中相等的元素所对应的下标属于同一组。例如,返回c(1, 2, 1, 3, 2), 表示根据传入的 indices ,第1、3个元素作为一组,第2、5个元素作为一组,第4个元素作为一组。
###其实就是用数字来分组而已,返回分组的数字。

v<-c(1:5)
v
[1] 1 2 3 4 5
ind <- c(‘a’,‘a’,‘a’,‘b’,‘b’)
ind
[1] “a” “a” “a” “b” “b”
tapply(v,ind)
[1] 1 1 1 2 2

v1<-5:9
v1
[1] 5 6 7 8 9
tapply(v1,ind)
[1] 1 1 1 2 2

##ind为indices的值,(数字因子)
按 indices 中的值分组,把相同值对应下标的array中的元素形成一个集合。

tapply(v, ind, sum)
a b
6 9
sum(v[1:3])
[1] 6
sum(v[4:5])
[1] 9
###a代表分组数字为1的前三个下标的为一组,b代表分组数字为2的另外2个为另外一组

二维array的例子(即matrix)

m <- matrix(c(1:10), nrow=2)
m
[,1] [,2] [,3] [,4] [,5]
[1,] 1 3 5 7 9
[2,] 2 4 6 8 10
ind <- matrix(c(rep(1,5), rep(2,5)), nrow=2)
ind
[,1] [,2] [,3] [,4] [,5]
[1,] 1 1 1 2 2
[2,] 1 1 2 2 2
tapply(m, ind)
[1] 1 1 1 1 1 2 2 2 2 2
tapply(m, ind, mean)
1 2
3 8

by(dataframe, INDICES, FUN, …, simplify=TRUE)
by 可以当成dataframe上的 tapply 。 indices 应当和dataframe每列的长度相同。返回值是 by 类型的object。若simplify=FALSE,本质上是个list。
数据框中元素的访问

通过下标进行访问,需要同时提供行和列对应的下标

mtcars[1:2, 1:2]

通过列名称和列对应的下标进行访问

mtcars$mpg
[1] 21.0 21.0 22.8 21.4 18.7 18.1 14.3 24.4 22.8 19.2 17.8 16.4 17.3 15.2
[15] 10.4 10.4 14.7 32.4 30.4 33.9 21.5 15.5 15.2 13.3 19.2 27.3 26.0 30.4
[29] 15.8 19.7 15.0 21.4
mtcars[[1]]
[1] 21.0 21.0 22.8 21.4 18.7 18.1 14.3 24.4 22.8 19.2 17.8 16.4 17.3 15.2
[15] 10.4 10.4 14.7 32.4 30.4 33.9 21.5 15.5 15.2 13.3 19.2 27.3 26.0 30.4
[29] 15.8 19.7 15.0 21.4

data <- data.frame(A = 1:3, B = c(“x1”, “x2”, “x3”), row.names=c(“R1”, “R2”, “R3”))
data
A B
R1 1 x1
R2 2 x2
R3 3 x3

A和B代表数据框中的列向量,row.names代表数据框的行名称。
通过read.table函数创建

R语言的主要用途之一就是数据处理,外部数据通过read.table函数读取进入R语言中,采用data.frame 这种数据格式进行存储,这也是数据框这种结构最常用的原因。

,row.names = 1代表使用第一列的内容作为数据框的行名称。header代表是否将文件的第一行作为数据框的列名称
和read.table函数相对应,write.table函数将数据框的内容写到文件中。

write.table(data, “data.csv”, sep = “,”)

###根据序列号排列

data <- data.frame(id = 1:3, weight = c(“x1”, “x2”, “x3”), size=c(“R1”, “R2”, “R3”))
data
id weight size
1 1 x1 R1
2 2 x2 R2
3 3 x3 R3
data[c(1,3,2)]
id size weight
1 1 R1 x1
2 2 R2 x2
3 3 R3 x3
data[c(“size”,“id”,“weight”)]
size id weight
1 R1 1 x1
2 R2 2 x2
3 R3 3 x3

我们也可以使用针对矩阵式的索引方式,例如data[row, col],需要注意的是,中括号中左侧为行,右侧为列。

data[,c(1,3,2)]
id weight size
1 1 x1 R1
2 2 x2 R2
3 3 x3 R3

矩阵式的索引方式有一个比较明显的缺点,当你明确的指定某一个数据框列进行索引时,它只会返回该列中的具体元素数值——也就是说,在这种情况下返回的结果是一个向量而非数据框,这是因为在矩阵式的索引的过程中返回的数据类型并不是固定不变的。所以相比之下,列表式索引更为保险,或者我们可以在矩阵式索引时加一个参数设置drop=FALSE:

data[2]
size
1 R1
2 R2
3 R3
#上为列表式
data[,2]
[1] R1 R2 R3
Levels: R1 R2 R3
#矩阵式索引为一个向量
data[,2,drop=FALSE]
size
1 R1
2 R2
3 R3

01

数组与矩阵

所谓数组,是相同数据类型的元素按一定顺序排列的集合。相应的,向量是“一维数组”;数组可以是多维的。包含多行、多列数据的一个数组中,数据既可以是数值,也可以是字符串。创建一个数组,要用到“array”函数;例如,创建一个由9 部电影名称组成的二维3×3 数组:

movie <- c(“Leon”,“Farewell My Concubine”,“Forrest Gump”,“La vita e bella”,“Spirited Away”,“Schindler’s List”, “Titanic”,“Inception”,“WALL·E”)
movie_array <- array(movie,dim=c(3,3))
movie_array
[,1] [,2] [,3]
[1,] “Leon” “La vita e bella” “Titanic”
[2,] “Farewell My Concubine” “Spirited Away” “Inception”
[3,] “Forrest Gump” “Schindler’s List” “WALL·E”

访问或提取数组中的某个元素,只需知道该元素的位置。例如,提取电影《泰坦尼克号(Titanic)》,它在第1 行、第3 列:

movie_array [1,3]
[1] “Titanic”

后在方括号中标明其位置即可。还可以提取某一行或某一列:

movie_array [1, ] # 提取第一行元素

movie_array [ ,2] # 提取第二列元素

矩阵与数组类似,只不过矩阵只能是二维的;创建一个矩阵,要用到“matrix”函数;需要注意的是,矩阵默认是把“列”优先存储的,需要通过“byrow”参数来优先存储“行”;例如在上面9 部电影中选取6 部创建一个3×2 矩阵:

movie <- c(“Leon”,“Farewell My Concubine”,“Forrest Gump”,“La vita e bella”,“Spirited Away”,“Schindler’s List”)

movie_matrix <- matrix(movie,nrow=3,ncol=2)

movie_matrix

movie_matrix <- matrix(movie,nrow=3,ncol=2,byrow=TRUE)

movie_matrix

方括号“[]”还可以提取数组的子集,对于矩阵也同样适用;例如提取“movie_array”这个数组后两行及前两列的4 部电影:

movie_array [2:3,1:2]

02

列表

列表与向量类似,只不过列表可以存储不同类型的数据;例如,可以把电影《这个杀手不太冷(Leon)》的信息用“list”函数存储为下面的一个列表:

movie2 <- list(“Leon”,1994,c(“drama”,“not-American”))
movie2
[[1]]
[1] “Leon”

[[2]]
[1] 1994

[[3]]
[1] “drama” “not-American”

该列表里包含3 类元素:一个字符串“Leon”,一个数值“1994”,一个向量“c(“drama”,“not-American”)”;访问和提取列表中的元素也使用方括号:

movie2 [1] # 访问列表中的第一个元素

movie2 [1:2] # 访问列表中的前两个元素

movie2 [1]
[[1]]
[1] “Leon”

movie2 [2]
[[1]]
[1] 1994

movie2 [3]
[[1]]
[1] “drama” “not-American”

除了根据索引值访问和提取列表中的元素,还有一种方法可以访问列表中的元素,即根据元素名称来访问,这就需要先给列表中的3 类元素命名,即“具名列表”:

movie2 <- list(name=“Leon”, year=1994, information=c(“drama”,“not-American”))
movie2
$name
[1] “Leon”

$year
[1] 1994

$information
[1] “drama” “not-American”

然后再用“$”函数或在方括号中加入引号“[""]”的方式来访问某元素:

movie2$name
[1] “Leon”
movie2[“name”]
$name
[1] “Leon”

添加列表元素,可以直接把元素名写入方括号中,再赋值;要想修改列表中元素的值,只需要对其重新赋值,覆盖原先的值;删除列表元素,可以对其赋NULL 值:

movie2 [“score”]<- 8.3 # 添加评分

movie2

movie2 [“score”]<- 9.4 # 修改评分

movie2

movie2 [“score”]<- NULL # 删除评分

movie2

03

数据框

创建数据框,需要用到“data.frame”函数,其每一个参数是一个向量;例如,创建一个包含6 部电影名称及上映时间的数据框:

movies <- data.frame (name=c(“Leon”,“Forrest Gump”,“Spirited Away”,“Schindler’s List”,“Titanic”,“Inception”),year=c(1994,1994,2001,1993,1997,2010))
movies
name year
1 Leon 1994
2 Forrest Gump 1994
3 Spirited Away 2001
4 Schindler’s List 1993
5 Titanic 1997
6 Inception 2010

访问数据框的列元素,可以用“$”函数或者在方括号中写入该列的序号:

movies$year

movies[2]

访问数据框的某个元素,可以在方括号中键入该元素的位置;例如,访问电影《这个杀手不太冷(Leon)》的上映时间:

movies[1,2]
[1] 1994

同在列表中添加元素类似,在数据框中增加一列,只需在方括号中添加该列名称,然后赋值:

movies [‘score’]<- c(9.4,9.4,9.2,9.4,9.2,9.2)

movies

在数据框中增加一行,则需要用到“rbind”函数,参数是数据框自身及包含每一列值的向量;例如,在这6 部电影信息基础上,再加1 部《黑鹰坠落(Black Hawk Down)》的信息:

movies <- rbind(movies,c(name=“Black Hawk Down”,year=2001,score=8.5))

movies

如果要删除某一行,在方括号中输入该列序号的负值即可,但列序号处要留空:

movies <- movies[-7, ]

movies

如果要删除某一列,直接在方括号中键入列名,并赋一个NULL 值即可:

movies [‘score’]<- NULL

movies

by
by(dataframe, INDICES, FUN, …, simplify=TRUE)
by 可以当成dataframe上的 tapply 。 indices 应当和dataframe每列的长度相同。返回值是 by 类型的object。若simplify=FALSE,本质上是个list。

df <- data.frame(a=c(1:5), b=c(6:10))
df
a b
1 1 6
2 2 7
3 3 8
4 4 9
5 5 10

ind <- c(1,1,1,2,2)
res <- by(df, ind, colMeans)
res
ind: 1
a b
2 7


ind: 2
a b
4.5 9.5
#colMeans为平价数,按照ind的映射,前三行作为一组,后两行作为一组

lapply
lapply(list, FUN, …)
在 list 上逐个元素调用 FUN 。可以用于dataframe上,因为dataframe是一种特殊形式的list。例

lst <- list(a=c(1:5), b=c(6:10))
lst
$a
[1] 1 2 3 4 5

$b
[1] 6 7 8 9 10

lapply(lst, mean)
$a
[1] 3

$b
[1] 8

发布了27 篇原创文章 · 获赞 3 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/qq_39306047/article/details/90671643