我们在数据分析的过程中经常会碰到不适合分析的数据格式,有的时候我们需要要画图或者建立n重交叉分析表,需要将长数据透视成宽数据;而有的时候宽数据不利于我们进行后续的分析,需要将数据转换成长数据。那什么是宽数据,什么是长数据呢?下面我们举个栗子看看吧。
-
宽数据
每一列为一个变量,每一行为变量所对应的值
> library(openxlsx)
> data = read.xlsx("/Users/afei/Desktop/test.xlsx")
> head(data)
组别 1月份 2月份 3月份 4月份 5月份 6月份
1 一组 40589 46475 54354 46497 40231 45402
2 二组 49351 54296 42200 47931 39243 41578
3 三组 41983 53099 39552 48860 53591 41799
4 四组 53883 52806 46719 38767 47856 42595
5 五组 41859 46403 45893 43950 51762 50848
6 六组 40231 48046 44355 49756 44490 50003
-
长数据
一列包含了所有的变量,而另一列则是与之相关的值
组别 月份 value
1 一组 1月份 40589
2 二组 1月份 49351
3 三组 1月份 41983
4 四组 1月份 53883
5 五组 1月份 41859
6 六组 1月份 40231
下面我们就来看看reshape2包里面可以转变长宽的两个非常重要的函数
- melt函数:将宽数据转换成长数据(逆透视)
- cast函数:将长数据转换成宽数据(透视)
1.melt
melt是一个泛型函数,在reshape2包中有分别用于数据框、数组和列表的melt方法。下面简单介绍各个参数。
- melt:
melt(data,id.vars,measure.vars,variable.name='variable',...,na.rm=FALSE,value.name='value',factorAsStrings=TRUE)
参数 | 描述 | 默认值 |
---|---|---|
data | 要溶解的数据框 | |
id.vars | ID变量(用于标识观察的变量) | 所有非测量变量。如果id.vars和measure.vars都没有设置,默认会使用所有的因子变量和字符变量 |
measure.vars | 测量变量(用于描述所测量的事物的变量) | 所有非ID变量。如果id.vars和measure.vars都没有设置,默认会使用所有的非因子和非字符变量 |
variable.name | 用于保存原始变量名的变量的名称 | "variable" |
value.name | 用于保存原始值的名称 | "value" |
na.rm | 告诉melt如何处理NA值 | FALSE |
factorAsStrings | 告诉melt是否要将字符变量转化成因子 | TRUE |
参数解释:
参数 | 描述 | 默认值 |
---|---|---|
data | 要溶解的数据框 | |
id.vars | ID变量(用于标识观察的变量) | 所有非测量变量。如果id.vars和measure.vars都没有设置,默认会使用所有的因子变量和字符变量 |
measure.vars | 测量变量(用于描述所测量的事物的变量) | 所有非ID变量。如果id.vars和measure.vars都没有设置,默认会使用所有的非因子和非字符变量 |
variable.name | 用于保存原始变量名的变量的名称 | "variable" |
value.name | 用于保存原始值的名称 | "value" |
na.rm | 告诉melt如何处理NA值 | FALSE |
factorAsStrings | 告诉melt是否要将字符变量转化成因子 | TRUE |
(1)只带有data参数的情况
我们可以看到如果id.vars和measure.vars都没有设置,默认会使用所有的因子变量和字符变量作为ID变量,使用所有的非因子和非字符变量作为测量变量
> head(iris)
Sepal.Length Sepal.Width Petal.Length Petal.Width Species
1 5.1 3.5 1.4 0.2 setosa
2 4.9 3.0 1.4 0.2 setosa
3 4.7 3.2 1.3 0.2 setosa
4 4.6 3.1 1.5 0.2 setosa
5 5.0 3.6 1.4 0.2 setosa
6 5.4 3.9 1.7 0.4 setosa
> test <- melt(iris)
Using Species as id variables
> head(test)
Species variable value
1 setosa Sepal.Length 5.1
2 setosa Sepal.Length 4.9
3 setosa Sepal.Length 4.7
4 setosa Sepal.Length 4.6
5 setosa Sepal.Length 5.0
6 setosa Sepal.Length 5.4
(2)使用id.vars参数的情况
> 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
3 12 149 12.6 74 5 3
4 18 313 11.5 62 5 4
5 NA NA 14.3 56 5 5
6 28 NA 14.9 66 5 6
> test2 <- melt(airquality,id.vars = c("Month","Day"))
> head(test2)
Month Day variable value
1 5 1 Ozone 41
2 5 2 Ozone 36
3 5 3 Ozone 12
4 5 4 Ozone 18
5 5 5 Ozone NA
6 5 6 Ozone 28
(3)使用measure.vars的情况
> 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
3 12 149 12.6 74 5 3
4 18 313 11.5 62 5 4
5 NA NA 14.3 56 5 5
6 28 NA 14.9 66 5 6
> test3 <- melt(airquality,id.vars = c("Month","Day"),measure.vars = "Ozone")
> head(test3)
Month Day variable value
1 5 1 Ozone 41
2 5 2 Ozone 36
3 5 3 Ozone 12
4 5 4 Ozone 18
5 5 5 Ozone NA
6 5 6 Ozone 28
> tail(test3)
Month Day variable value
148 9 25 Ozone 14
149 9 26 Ozone 30
150 9 27 Ozone NA
151 9 28 Ozone 14
152 9 29 Ozone 18
153 9 30 Ozone 20
(4)使用variable.name和value.name的情况
> 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
3 12 149 12.6 74 5 3
4 18 313 11.5 62 5 4
5 NA NA 14.3 56 5 5
6 28 NA 14.9 66 5 6
> test4 <- melt(airquality,id.vars = c("Month","Day"),measure.vars = c("Ozone","Temp"),variable.name="xixi",value.name = "haha")
> head(test4)
Month Day xixi haha
1 5 1 Ozone 41
2 5 2 Ozone 36
3 5 3 Ozone 12
4 5 4 Ozone 18
5 5 5 Ozone NA
6 5 6 Ozone 28
> tail(test4)
Month Day xixi haha
301 9 25 Temp 63
302 9 26 Temp 70
303 9 27 Temp 77
304 9 28 Temp 75
305 9 29 Temp 76
306 9 30 Temp 68
2.cast
cast函数在reshape2包中有好几个版本
- dcast:针对数据框
- acast:针对向量、矩阵、数组
平时数据框用的比较多,所以用dcast来演示
dcast公式
dcast(data, formula, fun.aggregate = NULL, ..., margins = NULL,subset = NULL, fill = NULL, drop = TRUE,value.var = guess_value(data))
参数 | 描述 | 默认值 |
---|---|---|
data | 以溶解的数据框(通常是melt函数创建的) | |
formula | 描述输出结果的公式,比如x~y,则x表示数据透视表的行,y代表数据透视表的列 | |
fun.aggregate | 聚合函数。如果要聚合输出结果中一溶解的数据,用这个参数可以设置聚合函数。可以使用自定义函数. | NULL |
margins | 相当于透视表中的行总计和列总计 | NULL |
subset | 选取满足一些特定值的数据,相当于Excel透视表的筛选。例如, subset =.(variable ==“length”) | NULL |
参数说明
参数 | 描述 | 默认值 |
---|---|---|
data | 以溶解的数据框(通常是melt函数创建的) | |
formula | 描述输出结果的公式,比如x~y,则x表示数据透视表的行,y代表数据透视表的列 | |
fun.aggregate | 聚合函数。如果要聚合输出结果中一溶解的数据,用这个参数可以设置聚合函数。可以使用自定义函数. | NULL |
margins | 相当于透视表中的行总计和列总计 | NULL |
subset | 选取满足一些特定值的数据,相当于Excel透视表的筛选。例如, subset =.(variable ==“length”) | NULL |
例子说明
> names(airquality) <- tolower(names(airquality))
> aqm <- melt(airquality, id=c("month", "day"), na.rm=TRUE)
> head(aqm)
month day variable value
1 5 1 ozone 41
2 5 2 ozone 36
3 5 3 ozone 12
4 5 4 ozone 18
6 5 6 ozone 28
7 5 7 ozone 23
-----------------------------------------------------------------
**计算按月份分组的每个变量的均值**
> dcast(aqm, month ~ variable, mean, margins = c("month", "variable"),na.rm=TRUE)
month ozone solar.r wind temp (all)
1 5 23.61538 181.2963 11.622581 65.54839 68.70696
2 6 29.44444 190.1667 10.266667 79.10000 87.38384
3 7 59.11538 216.4839 8.941935 83.90323 93.49748
4 8 59.96154 171.8571 8.793548 83.96774 79.71207
5 9 31.44828 167.4333 10.180000 76.90000 71.82689
6 (all) 42.12931 185.9315 9.957516 77.88235 80.05722
-----------------------------------------------------------------
**和上面的例子对调了一下行和列**
> dcast(aqm, variable ~ month, mean, margins = c("month", "variable"))
variable 5 6 7 8 9 (all)
1 ozone 23.61538 29.44444 59.115385 59.961538 31.44828 42.129310
2 solar.r 181.29630 190.16667 216.483871 171.857143 167.43333 185.931507
3 wind 11.62258 10.26667 8.941935 8.793548 10.18000 9.957516
4 temp 65.54839 79.10000 83.903226 83.967742 76.90000 77.882353
5 (all) 68.70696 87.38384 93.497479 79.712069 71.82689 80.057218
-----------------------------------------------------------------
> names(airquality) <- tolower(names(airquality))
> aqm <- melt(airquality, id=c("month", "day"), na.rm=TRUE)
> head(aqm)
month day variable value
1 5 1 ozone 41
2 5 2 ozone 36
3 5 3 ozone 12
4 5 4 ozone 18
6 5 6 ozone 28
7 5 7 ozone 23
> acast(aqm,day~month~variable)
, , ozone
5 6 7 8 9
1 41 NA 135 39 96
2 36 NA 49 9 78
3 12 NA 32 16 73
4 18 NA NA 78 91
5 NA NA 64 35 47
6 28 NA 40 66 32
7 23 29 77 122 20
8 19 NA 97 89 23
9 8 71 97 110 21
10 NA 39 85 NA 24
11 7 NA NA NA 44
12 16 NA 10 44 21
13 11 23 27 28 28
14 14 NA NA 65 9
15 18 NA 7 NA 13
16 14 21 48 22 46
17 34 37 35 59 18
18 6 20 61 23 13
19 30 12 79 31 24
20 11 13 63 44 16
21 1 NA 16 21 13
22 11 NA NA 9 23
23 4 NA NA NA 36
24 32 NA 80 45 7
25 NA NA 108 168 14
26 NA NA 20 73 30
27 NA NA 52 NA NA
28 23 NA 82 76 14
29 45 NA 50 118 18
30 115 NA 64 84 20
31 37 NA 59 85 NA
, , solar.r
5 6 7 8 9
1 190 286 269 83 167
2 118 287 248 24 197
3 149 242 236 77 183
4 313 186 101 NA 189
5 NA 220 175 NA 95
6 NA 264 314 NA 92
7 299 127 276 255 252
8 99 273 267 229 220
9 19 291 272 207 230
10 194 323 175 222 259
11 NA 259 139 137 236
12 256 250 264 192 259
13 290 148 175 273 238
14 274 332 291 157 24
15 65 322 48 64 112
16 334 191 260 71 237
17 307 284 274 51 224
18 78 37 285 115 27
19 322 120 187 244 238
20 44 137 220 190 201
21 8 150 7 259 238
22 320 59 258 36 14
23 25 91 295 255 139
24 92 250 294 212 49
25 66 135 223 238 20
26 266 127 81 215 193
27 NA 47 82 153 145
28 13 98 213 203 191
29 252 31 275 225 131
30 223 138 253 237 223
31 279 NA 254 188 NA
, , wind
5 6 7 8 9
1 7.4 8.6 4.1 6.9 6.9
2 8.0 9.7 9.2 13.8 5.1
3 12.6 16.1 9.2 7.4 2.8
4 11.5 9.2 10.9 6.9 4.6
5 14.3 8.6 4.6 7.4 7.4
6 14.9 14.3 10.9 4.6 15.5
7 8.6 9.7 5.1 4.0 10.9
8 13.8 6.9 6.3 10.3 10.3
9 20.1 13.8 5.7 8.0 10.9
10 8.6 11.5 7.4 8.6 9.7
11 6.9 10.9 8.6 11.5 14.9
12 9.7 9.2 14.3 11.5 15.5
13 9.2 8.0 14.9 11.5 6.3
14 10.9 13.8 14.9 9.7 10.9
15 13.2 11.5 14.3 11.5 11.5
16 11.5 14.9 6.9 10.3 6.9
17 12.0 20.7 10.3 6.3 13.8
18 18.4 9.2 6.3 7.4 10.3
19 11.5 11.5 5.1 10.9 10.3
20 9.7 10.3 11.5 10.3 8.0
21 9.7 6.3 6.9 15.5 12.6
22 16.6 1.7 9.7 14.3 9.2
23 9.7 4.6 11.5 12.6 10.3
24 12.0 6.3 8.6 9.7 10.3
25 16.6 8.0 8.0 3.4 16.6
26 14.9 8.0 8.6 8.0 6.9
27 8.0 10.3 12.0 5.7 13.2
28 12.0 11.5 7.4 9.7 14.3
29 14.9 14.9 7.4 2.3 8.0
30 5.7 8.0 7.4 6.3 11.5
31 7.4 NA 9.2 6.3 NA
, , temp
5 6 7 8 9
1 67 78 84 81 91
2 72 74 85 81 92
3 74 67 81 82 93
4 62 84 84 86 93
5 56 85 83 85 87
6 66 79 83 87 84
7 65 82 88 89 80
8 59 87 92 90 78
9 61 90 92 90 75
10 69 87 89 92 73
11 74 93 82 86 81
12 69 92 73 86 76
13 66 82 81 82 77
14 68 80 91 80 71
15 58 79 80 79 71
16 64 77 81 77 78
17 66 72 82 79 67
18 57 65 84 76 76
19 68 73 87 78 68
20 62 76 85 78 82
21 59 77 74 77 64
22 73 76 81 72 71
23 61 76 82 75 81
24 61 76 86 79 69
25 57 75 85 81 63
26 58 78 82 86 70
27 57 73 86 88 77
28 67 80 88 97 75
29 81 77 86 94 76
30 79 83 83 96 68
31 76 NA 81 94 NA
-----------------------------------------------------------------
**加margins参数的情况**
**注意acast和dcast函数之间的区别**
> acast(aqm,month~variable,mean)
ozone solar.r wind temp
5 23.61538 181.2963 11.622581 65.54839
6 29.44444 190.1667 10.266667 79.10000
7 59.11538 216.4839 8.941935 83.90323
8 59.96154 171.8571 8.793548 83.96774
9 31.44828 167.4333 10.180000 76.90000
> acast(aqm, month ~ variable, mean, margins = TRUE)
ozone solar.r wind temp (all)
5 23.61538 181.2963 11.622581 65.54839 68.70696
6 29.44444 190.1667 10.266667 79.10000 87.38384
7 59.11538 216.4839 8.941935 83.90323 93.49748
8 59.96154 171.8571 8.793548 83.96774 79.71207
9 31.44828 167.4333 10.180000 76.90000 71.82689
(all) 42.12931 185.9315 9.957516 77.88235 80.05722
> dcast(aqm,month~variable,mean)
month ozone solar.r wind temp
1 5 23.61538 181.2963 11.622581 65.54839
2 6 29.44444 190.1667 10.266667 79.10000
3 7 59.11538 216.4839 8.941935 83.90323
4 8 59.96154 171.8571 8.793548 83.96774
5 9 31.44828 167.4333 10.180000 76.90000
> dcast(aqm,month~variable,mean,margins=TRUE)
month ozone solar.r wind temp (all)
1 5 23.61538 181.2963 11.622581 65.54839 68.70696
2 6 29.44444 190.1667 10.266667 79.10000 87.38384
3 7 59.11538 216.4839 8.941935 83.90323 93.49748
4 8 59.96154 171.8571 8.793548 83.96774 79.71207
5 9 31.44828 167.4333 10.180000 76.90000 71.82689
6 (all) 42.12931 185.9315 9.957516 77.88235 80.05722
> dcast(aqm, month ~ variable, mean, margins = c("month", "variable"))
month ozone solar.r wind temp (all)
1 5 23.61538 181.2963 11.622581 65.54839 68.70696
2 6 29.44444 190.1667 10.266667 79.10000 87.38384
3 7 59.11538 216.4839 8.941935 83.90323 93.49748
4 8 59.96154 171.8571 8.793548 83.96774 79.71207
5 9 31.44828 167.4333 10.180000 76.90000 71.82689
6 (all) 42.12931 185.9315 9.957516 77.88235 80.05722
-----------------------------------------------------------------
**使用subset参数的情况**
> library(plyr) #为了使用.函数
> dcast(aqm,variable~month,mean)
variable 5 6 7 8 9
1 ozone 23.61538 29.44444 59.115385 59.961538 31.44828
2 solar.r 181.29630 190.16667 216.483871 171.857143 167.43333
3 wind 11.62258 10.26667 8.941935 8.793548 10.18000
4 temp 65.54839 79.10000 83.903226 83.967742 76.90000
> dcast(aqm,variable~month,mean,subset=.(variable=="ozone"))
variable 5 6 7 8 9
1 ozone 23.61538 29.44444 59.11538 59.96154 31.44828
> dcast(aqm,variable~month,mean,subset=.(month==5))
variable 5
1 ozone 23.61538
2 solar.r 181.29630
3 wind 11.62258
4 temp 65.54839
> dcast(aqm,variable~month,mean,subset=.(variable=="ozone" & month==5))
variable 5
1 ozone 23.61538
-----------------------------------------------------------------
**n重交叉分析表**
> names(ChickWeight) <- tolower(names(ChickWeight))
> chick_m <- melt(ChickWeight, id=2:4, na.rm=TRUE)
>
> head(chick_m)
time chick diet variable value
1 0 1 1 weight 42
2 2 1 1 weight 51
3 4 1 1 weight 59
4 6 1 1 weight 64
5 8 1 1 weight 76
6 10 1 1 weight 93
> head(ChickWeight)
weight time chick diet
1 42 0 1 1
2 51 2 1 1
3 59 4 1 1
4 64 6 1 1
5 76 8 1 1
6 93 10 1 1
> head(dcast(chick_m,diet+chick~time))
diet chick 0 2 4 6 8 10 12 14 16 18 20 21
1 1 18 39 35 NA NA NA NA NA NA NA NA NA NA
2 1 16 41 45 49 51 57 51 54 NA NA NA NA NA
3 1 15 41 49 56 64 68 68 67 68 NA NA NA NA
4 1 13 41 48 53 60 65 67 71 70 71 81 91 96
5 1 9 42 51 59 68 85 96 90 92 93 100 100 98
6 1 20 41 47 54 58 65 73 77 89 98 107 115 117
> head(dau.user.info)
log_date app_name user_id install_date gender generation device_type
1 2013-08-01 game-01 33754 2013-08-01 M 20 iOS
2 2013-08-01 game-01 28598 2013-07-16 M 50 iOS
3 2013-08-01 game-01 30306 2013-07-20 F 30 iOS
4 2013-08-01 game-01 117 2013-04-17 F 20 iOS
5 2013-08-01 game-01 6605 2013-05-02 M 20 iOS
6 2013-08-01 game-01 346 2013-04-18 F 30 iOS
log_month
1 2013-08
2 2013-08
3 2013-08
4 2013-08
5 2013-08
6 2013-08
> dcast(dau.user.info,log_month~gender+generation,value.var = "user_id",length)
log_month F_10 F_20 F_30 F_40 F_50 M_10 M_20 M_30 M_40 M_50
1 2013-08 9091 17181 14217 4597 2257 9694 16490 13855 4231 2572
2 2013-09 7316 13616 11458 3856 1781 8075 13613 10768 3638 2054
------------------------------分割线-----------------------------------
下面介绍一下reshape包中的cast函数
reshape包和reshape2包都是同一个人开发的,所以melt和cast函数大同小异
**生成数据**
> states <- data.frame(state=row.names(state.x77),region=state.region,state.x77,row.names=1:50)
> head(states)
state region Population Income Illiteracy Life.Exp Murder HS.Grad
1 Alabama South 3615 3624 2.1 69.05 15.1 41.3
2 Alaska West 365 6315 1.5 69.31 11.3 66.7
3 Arizona West 2212 4530 1.8 70.55 7.8 58.1
4 Arkansas South 2110 3378 1.9 70.66 10.1 39.9
5 California West 21198 5114 1.1 71.71 10.3 62.6
6 Colorado West 2541 4884 0.7 72.06 6.8 63.9
Frost Area
1 20 50708
2 152 566432
3 15 113417
4 65 51945
5 20 156361
6 166 103766
-----------------------------------------------------------------
**融合数据**
> test <- melt(states)
Using state, region as id variables
> head(test)
state region variable value
1 Alabama South Population 3615
2 Alaska West Population 365
3 Arizona West Population 2212
4 Arkansas South Population 2110
5 California West Population 21198
6 Colorado West Population 2541
-----------------------------------------------------------------
**使用自定义函数**
fun <- function(x){
require('fBasics')
n = sum(!is.na(x))
nmiss = sum(is.na(x))
m=mean(x,na.rm = TRUE)
s = sd(x,na.rm = TRUE)
max = max(x,na.rm = TRUE)
min = min(x,na.rm=TRUE)
return(c(nomiss = n,miss=nmiss,mean=m,sd=s,max=max,min=min))
}
> library(reshape)
> cast(test,variable~.|Species,fun) #将输出结果设置为列表格式(加了.|,dcast好像不能这样写)
$setosa
variable nomiss miss mean sd max min
1 Sepal.Length 50 0 5.006 0.3524897 5.8 4.3
2 Sepal.Width 50 0 3.428 0.3790644 4.4 2.3
3 Petal.Length 50 0 1.462 0.1736640 1.9 1.0
4 Petal.Width 50 0 0.246 0.1053856 0.6 0.1
$versicolor
variable nomiss miss mean sd max min
1 Sepal.Length 50 0 5.936 0.5161711 7.0 4.9
2 Sepal.Width 50 0 2.770 0.3137983 3.4 2.0
3 Petal.Length 50 0 4.260 0.4699110 5.1 3.0
4 Petal.Width 50 0 1.326 0.1977527 1.8 1.0
$virginica
variable nomiss miss mean sd max min
1 Sepal.Length 50 0 6.588 0.6358796 7.9 4.9
2 Sepal.Width 50 0 2.974 0.3224966 3.8 2.2
3 Petal.Length 50 0 5.552 0.5518947 6.9 4.5
4 Petal.Width 50 0 2.026 0.2746501 2.5 1.4
-----------------------------------------------------------------
**多变量分组统计**
> data <- data.frame(x=rpois(100,2),y=rpois(100,3),z=runif(100,10,20))
> head(data)
x y z
1 2 3 19.39958
2 1 3 13.69048
3 3 4 10.29499
4 2 3 10.67246
5 2 1 19.03233
6 3 2 19.79894
> m_data <- melt(data,measure.vars="z")
**dcast也做不了c(mean,min,max,median)**
> head(cast(m_data,x+y~variable,c(mean,min,max,median)))
x y z_mean z_min z_max z_median
1 0 0 14.87159 14.87159 14.87159 14.87159
2 0 1 16.43556 12.88235 19.98877 16.43556
3 0 2 14.92238 10.99968 19.55458 14.56764
4 0 3 15.14760 12.90916 16.56199 15.26421
5 0 4 14.65345 12.75043 16.55647 14.65345
6 0 5 11.07558 11.07558 11.07558 11.07558
网友评论
这种数据
ksh option1 score1 option2 score2
1: 1 A 3 C 3
2: 2 B 2 D 1
如何揉成这种
ksh option score
1 A 3
2 B 2
1 C 3
2 D 1
data <- data.frame(ksh=c(1,2),option1=c("A","B"),score1=c(3,2),option2=c("C","D"),score2=c(3,1))
data1 <- select(data,c("ksh","option1","score1"))
names(data1) <- c("ksh","option","score")
data2 <- select(data,c("ksh","option2","score2"))
names(data2) <- c("ksh","option","score")
rbind(data1,data2)