matrix, array, as.vector, list unlist
matrix及as.vector
据整形最直接的思路就把数据全部向量化,然后按要求用向量构建其他类型的数据。这样是不是会产生大量的中间变量、占用大量内存?没错。R语言的任何函数(包括赋值)操作都会有同样的问题,因为R函数的参数传递方式是传值不传址,变量不可能原地址修改后再放回原地址。
矩阵和多维数组的向量化有直接的类型转换函数: as.vector,向量化后的结果顺序是先列后行再其他:
>(x <- matrix(1:4, ncol=2)) #为节省空间,下面的结果省略了一些空行
[,1] [,2]
[1,] 1 3
[2,] 2 4
> as.vector(x)
[1] 1 2 3 4
> (x <- array(1:8, dim=c(2,2,2)))
, , 1
[,1] [,2]
[1,] 1 3
[2,] 2 4
, , 2
[,1] [,2]
[1,] 5 7
[2,] 6 8
> as.vector(x)
[1] 1 2 3 4 5 6 7 8
list及unlist
列表向量化可以用unlist,数据框本质是元素长度相同的列表,所以也用unlist:
> (x <- list(x=1:3, y=5:10))
$x
[1] 1 2 3
$y
[1] 5 6 7 8 9 10
> unlist(x)
x1 x2 x3 y1 y2 y3 y4 y5 y6
1 2 3 5 6 7 8 9 10
> x <- data.frame(x=1:3, y=5:7)
> x
x y
1 1 5
2 2 6
3 3 7
> unlist(x)
x1 x2 x3 y1 y2 y3
1 2 3 5 6 7
其他类型的数据一般都可以通过数组、矩阵或列表转成向量。一些软件包有自定义的数据类型,如果考虑周到的话应该会有合适的类型转换函数。
array与matrix
- 用函数array()或matrix()可以更直观地定义数组。array()函数的完全使用为array(x, dim=length(x), dimnames=NULL),其中x是第一自变量,应该是一个向量,表示数组的元素值组成的向量。dim参数可省,省略时作为一维数组(但不同于向量)。dimnames属性可以省略。
- 矩阵是二维数组,但因为其应用广泛所以对它定义了一些特殊的运算和操作。
- 函数t(A)返回矩阵A的转置。nrow(A)为矩阵A的行数,ncol(A)为矩阵A的列数。
- 矩阵之间进行普通的加减乘除四则运算仍遵从一般的数组四则运算规则,即数组的对应元素之间进行运算,所以注意A*B不是矩阵乘法而是矩阵对应元素相乘。
- 要进行矩阵乘法,使用运算符%%,A%%B表示矩阵A乘以矩阵B(当然要求A的列数等于B的行数)
transform, subset和within函数
transform 函数对数据框进行操作,作用是为原数据框增加新的列变量。但应该注意的是“原数据框”根本不是原来的那个数据框,而是一个它的拷贝。
> head(airquality)
Ozone Solar.R Wind Temp Month Day
1 41 190 7.4 67 5 1
2 36 118 8.0 72 5 2
> transform(airquality, Ozone = -Ozone)
Ozone Solar.R Wind Temp Month Day
1 -41 190 7.4 67 5 1
2 -36 118 8.0 72 5 2
> transform(airquality, new = -Ozone, Temp = (Temp-32)/1.8)#增加一列
Ozone Solar.R Wind Temp Month Day new
1 41 190 7.4 19.44444 5 1 -41
> attach(airquality)
> transform(Ozone, logOzone = log(Ozone))
X_data logOzone
1 41 3.713572
2 36 3.583519
transform可以增加新列变量,可以改变列变量的值,也可以通过NULL赋值的方式删除列变量:
> aq <- transform(airquality, log.ozone=log(Ozone), Ozone=NULL, Wind=Wind^2)
> head(aq)
Solar.R Wind Temp Month Day loglog.ozone WindWind
1 190 7.4 67 5 1 3.713572 54.76
within 比 transform 灵活些,除数据框外还可以使用其他类型数据,但用法不大一样。用法为:
within(data, expr, …) 其中expr为要计算的式子
> aq <- within(airquality, { # Notice that multiple vars can be changed
+ lOzone <- log(Ozone)
+ Month <- factor(month.abb[Month])
+ cTemp <- round((Temp - 32) * 5/9, 1) # From Fahrenheit to Celsius
+ S.cT <- Solar.R / cTemp # using the newly created variable
+ rm(Day, Temp)
+ }) #rm表示remove
> head(aq)
Ozone Solar.R Wind Month S.cT cTemp lOzone
1 41 190 7.4 May 9.793814 19.4 3.713572
2 36 118 8.0 May 5.315315 22.2 3.583519
> with(data.frame(u = c(5,10,15,20,30,40,60,80,100),
+ lot1 = c(118,58,42,35,27,25,21,19,18),
+ lot2 = c(69,35,26,21,18,16,13,12,12)),
+ list(summary(glm(lot1 ~ log(u), family = Gamma)),
+ summary(glm(lot2 ~ log(u), family = Gamma))))
[[1]]
Call:
glm(formula = lot1 ~ log(u), family = Gamma)
Deviance Residuals:
Min 1Q Median 3Q Max
-0.04008 -0.03756 -0.02637 0.02905 0.08641
Coefficients:
Estimate Std. Error t value Pr(>|t|)
(Intercept) -0.0165544 0.0009275 -17.85 4.28e-07 ***
log(u) 0.0153431 0.0004150 36.98 2.75e-09 ***
---
Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
(Dispersion parameter for Gamma family taken to be 0.002446059)
Null deviance: 3.51283 on 8 degrees of freedom
Residual deviance: 0.01673 on 7 degrees of freedom
AIC: 37.99
Number of Fisher Scoring iterations: 3
[[2]]
Call:
glm(formula = lot2 ~ log(u), family = Gamma)
Deviance Residuals:
Min 1Q Median 3Q Max
-0.05574 -0.02925 0.01030 0.01714 0.06371
Coefficients:
Estimate Std. Error t value Pr(>|t|)
(Intercept) -0.0239085 0.0013265 -18.02 4.00e-07 ***
log(u) 0.0235992 0.0005768 40.91 1.36e-09 ***
---
Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
(Dispersion parameter for Gamma family taken to be 0.001813354)
Null deviance: 3.118557 on 8 degrees of freedom
Residual deviance: 0.012672 on 7 degrees of freedom
AIC: 27.032
Number of Fisher Scoring iterations: 3
subset是返回满足条件的子集:
> subset(airquality, Temp > 80, select = c(Ozone, Temp))
Ozone Temp
29 45 81
35 NA 84
> subset(airquality, Day == 1, select = -Temp) #不选取temp列
Ozone Solar.R Wind Month Day
1 41 190 7.4 5 1
32 NA 286 8.6 6 1
> subset(airquality, select = Ozone:Wind)
Ozone Solar.R Wind
1 41 190 7.4
2 36 118 8.0
stack和unstack(类似excel数据透视)
stack 和 unstack 的作用和reshape类似,用于数据框/列表的长、宽格式之间转换。数据框宽格式是我们记录原始数据常用的格式,类似
> formula(PlantGrowth)
weight ~ group
> head(PlantGrowth)
weight group
1 4.17 ctrl
2 5.58 ctrl
> pg <- unstack(PlantGrowth) # unstack according to this formula
> pg
ctrl trt1 trt2
1 4.17 4.81 6.31
2 5.58 4.17 5.12
> stack(pg) # now put it back together
values ind
1 4.17 ctrl
> stack(pg, select = -ctrl)
values ind
1 4.81 trt1
2 4.17 trt1