R语言-数据整形之简介
R语言中数据整形
前言
从不同途径得到的数据的组织方式是多种多样的,很多数据都要经过整理才能进行有效的分析,数据整形不仅仅是为了改善数据的外观,也是进行一些统计分析和作图前必要的步骤。数据整形和数据凝练/汇总往往密不可分,这是门学问,是R语言数据处理的内容之一。
目录
1. 通过重新构建数据进行整形
2. transform 和 within 函数
3. stack 和 unstack 函数
1. 通过重新构建数据进行整形
数据整形最直接的思路就把数据全部向量化,然后按要求用向量构建其他类型的数据。这样是不是会产生大量的中间变量、占用大量内存?没错。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
列表向量化可以用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)
> unlist(x)
x1 x2 x3 y1 y2 y3
1 2 3 5 6 7
其他类型的数据一般都可以通过数组、矩阵或列表转成向量。一些软件包有自定义的数据类型,如果考虑周到的话应该会有合适的类型转换函数。
2. transform 和 within 函数
transform 函数对数据框进行操作,作用是为原数据框增加新的列变量。但应该注意的是“原数据框”根本不是原来的那个数据框,而是一个它的拷贝。下面代码为airquality数据框增加了一列log.ozone,但因为没有把结果赋值给原变量名,所以原数据是不变的:
> head(airquality,2)
Ozone Solar.R Wind Temp Month Day
1 41 190 7.4 67 5 1
2 36 118 8.0 72 5 2
> aq <- transform(airquality, log.ozone=log(Ozone))
> head(airquality,2)
Ozone Solar.R Wind Temp Month Day
1 41 190 7.4 67 5 1
2 36 118 8.0 72 5 2
> head(aq,2)
Ozone Solar.R Wind Temp Month Day log.ozone
1 41 190 7.4 67 5 1 3.713572
2 36 118 8.0 72 5 2 3.583519
transform可以增加新列变量,可以改变列变量的值,也可以通过NULL赋值的方式删除列变量:
> aq <- transform(airquality, log.ozone=log(Ozone), Ozone=NULL, Wind=Wind^2)
> head(aq,2)
Solar.R Wind Temp Month Day log.ozone
1 190 54.76 67 5 1 3.713572
2 118 64.00 72 5 2 3.583519
> aq <- transform(airquality, log.ozone=log(Ozone), Ozone=NULL, Month=NULL, Wind=Wind^2)
> head(aq,2)
Solar.R Wind Temp Day log.ozone
1 190 54.76 67 1 3.713572
2 118 64.00 72 2 3.583519
within 比 transform 灵活些,除数据框外还可以使用其他类型数据,但用法不大一样,而且函数似乎也不够完善:
> aq <- within(airquality, {
+ log.ozone <- log(Ozone)
+ squared.wind <- Wind^2
+ rm(Ozone, Wind)
+ } )
> head(aq,2)
Solar.R Temp Month Day squared.wind log.ozone
1 190 67 5 1 54.76 3.713572
2 118 72 5 2 64.00 3.583519
> (x <- list(a=1:3, b=letters[3:10], c=LETTERS[9:14]))
$a
[1] 1 2 3
$b
[1] "c" "d" "e" "f" "g" "h" "i" "j"
$c
[1] "I" "J" "K" "L" "M" "N"
> within(x, {log.a <- log(a); d <- paste(b, c, sep=':'); rm(b)})
$a
[1] 1 2 3
$c
[1] "I" "J" "K" "L" "M" "N"
$d
[1] "c:I" "d:J" "e:K" "f:L" "g:M" "h:N" "i:I" "j:J"
$log.a
[1] 0.0000000 0.6931472 1.0986123
> within(x, {log.a <- log(a); d <- paste(b, c, sep=':'); rm(b,c)})
$a
[1] 1 2 3
$b #为什么删除两个列表元素会得到这样的结果?
NULL
$c
NULL
$d
[1] "c:I" "d:J" "e:K" "f:L" "g:M" "h:N" "i:I" "j:J"
$log.a
[1] 0.0000000 0.6931472 1.0986123
3. stack 和 unstack 函数
stack 和 unstack 的作用和reshape类似,用于数据框/列表的长、宽格式之间转换。数据框宽格式是我们记录原始数据常用的格式,类似这样:
> x <- data.frame(CK=c(1.1, 1.2, 1.1, 1.5), T1=c(2.1, 2.2, 2.3, 2.1), T2=c(2.5, 2.2, 2.3, 2.1))
> x
CK T1 T2
1 1.1 2.1 2.5
2 1.2 2.2 2.2
3 1.1 2.3 2.3
4 1.5 2.1 2.1
一般统计和作图用的是长格式,stack可以做这个:
> (xx <- stack(x))
values ind
1 1.1 CK
2 1.2 CK
3 1.1 CK
4 1.5 CK
5 2.1 T1
6 2.2 T1
7 2.3 T1
8 2.1 T1
9 2.5 T2
10 2.2 T2
11 2.3 T2
12 2.1 T2
而unstack的作用正好和stack相反,但是要注意它的第二个参数是公式类型:公式左边的变量是值,右边的变量会被当成因子类型,它的每个水平都会形成一列:
> unstack(xx, values~ind)
CK T1 T2
1 1.1 2.1 2.5
2 1.2 2.2 2.2
3 1.1 2.3 2.3
4 1.5 2.1 2.1
参考资料
©哈尔滨商业大学 银河统计工作室
银河统计工作室成员由在校统计、计算机部分师生和企业数据数据分析师组成,维护和开发银河统计网和银河统计博客(技术文档)。专注于数据挖掘技术研究和运用,探索统计学、应用数学和IT技术有机结合,尝试大数据条件下新型统计学教学模式。