reshape2包使用
冯洋洋
2017年10月31日
1.reshape2包简介
reshap2包包含了一些对数据进行重构的函数,是reshape包的升级版本,作者Hadley Wickham h.wickham@gmail.com。 数据重构一般是指数据形态、格式以及数据类型的转换,将数据从一种数据形态转换到另一种数据形态,从一种数据格式转换到另一种格式……。通常,这意味着需要对数据进行维度转换,reshape2包就是为此而开发的。
2.reshape2包中的函数
2.1 acast
- 功能
功能在2.3节已经介绍的很详细了,现在主要介绍acast函数的使用方法以及返回的结果。 acast返回的是一个数组,其中~左侧的作为行名,~右侧的作为列名。假设有一个已经经过melt的数据集melt.v,其前几行如下所示
head(melt.v)
## m d pg finished
## 1 6 1 pg1 11.19101
## 2 6 2 pg1 14.41018
## 3 6 3 pg1 19.27001
## 4 6 4 pg1 15.16469
## 5 6 5 pg1 12.59584
## 6 6 1 pg2 15.23242
其中,pg表示项目组,finished表示完工百分比。
现在,假设我要求每个项目组的进度,即一共完成了百分之多少,则通过如下操作完成:
acast(melt.v,pg~m,fun.aggregate = sum)
## 6
## pg1 72.63173
## pg2 71.87603
## pg3 80.66047
可以看出,公式的两边要求最好是分类变量,然后才能进行聚合运算。如果把cast的返回结果理解为列联表,那么就比较容易理解了。列联表的两个变量肯定都是分类变量。 上面的数据量太小,下面我们用R中自带的数据集airquality来进行演示,展示更多的功能。 airquality是一个记录了空气质量的数据集,是一个154行6列的数据框,各列详情如下所示:
Ozone: Mean ozone in parts per billion from 1300 to 1500 hours at Roosevelt Island(臭氧浓度)
Solar.R: Solar radiation in Langleys in the frequency band 4000–7700 Angstroms from 0800 to 1200 hours at Central Park(阳光辐射)
Wind: Average wind speed in miles per hour at 0700 and 1000 hours at LaGuardia Airport(风速)
Temp: Maximum daily temperature in degrees Fahrenheit at La Guardia Airport.(最高温度)
month:(月份)
day:(日期)
那么,首先对此数据进行融合:
#由于具有缺失值,此时na.rm设置为TRUE
names(airquality) <-tolower(names(airquality))
melt.air <-melt(airquality,id.vars = c('month','day'),variable.name = 'index',na.rm = TRUE)
summary(melt.air)
## month day index value
## Min. :5.000 Min. : 1.00 ozone :116 Min. : 1.00
## 1st Qu.:6.000 1st Qu.: 8.00 solar.r:146 1st Qu.: 13.00
## Median :7.000 Median :16.00 wind :153 Median : 66.00
## Mean :7.044 Mean :15.83 temp :153 Mean : 80.06
## 3rd Qu.:8.000 3rd Qu.:23.00 3rd Qu.: 91.00
## Max. :9.000 Max. :31.00 Max. :334.00
融合以后的数据如上所示。根据上面的数据,我们可以进行许多分析。
- 计算每个月各个指标的平均值:
acast(data = melt.air,formula = month~index,fun.aggregate = 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
- 使用dcast运行上述函数。
dcast(data = melt.air,formula = month~index,fun.aggregate = 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会为月份添加一个列名——因为要返回数据框的形式。
- 按照日期-月份-指标,生成一个三维数组。
acast(melt.air,day~month~index)
## , , 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
使用ChickWeight数据集完成一些更有趣的操作。ChickWeight是一个578行4列的数据集,各个变量介绍如下:
weight:a numeric vector giving the body weight of the chick (gm)(小鸡体重).
Time:a numeric vector giving the number of days since birth when the measurement was made(小鸡出生时长,按天计算).
Chick:an ordered factor with levels 18 < ... < 48 giving a unique identifier for the chick. The ordering of the levels groups chicks on the same diet together and orders them according to their final weight (lightest to heaviest) within diet(根据体重对小鸡进行分组,每组内喂食量一致).
Diet:a factor with levels 1, ..., 4 indicating which experimental diet the chick received(试验编号).
- 行名还可以是两个分类变量的组合,组合以后的每个行名都是唯一的。
names(ChickWeight) <-tolower(names(ChickWeight))
melt.chick <-melt(ChickWeight,id.vars = 2:4,na.rm = TRUE,variable.name = 'weight')
summary(melt.chick)
## time chick diet weight value
## Min. : 0.00 13 : 12 1:220 weight:578 Min. : 35.0
## 1st Qu.: 4.00 9 : 12 2:120 1st Qu.: 63.0
## Median :10.00 20 : 12 3:120 Median :103.0
## Mean :10.72 10 : 12 4:118 Mean :121.8
## 3rd Qu.:16.00 17 : 12 3rd Qu.:163.8
## Max. :21.00 19 : 12 Max. :373.0
## (Other):506
acast(melt.chick,chick+diet~time)
## 0 2 4 6 8 10 12 14 16 18 20 21
## 18_1 39 35 NA NA NA NA NA NA NA NA NA NA
## 16_1 41 45 49 51 57 51 54 NA NA NA NA NA
## 15_1 41 49 56 64 68 68 67 68 NA NA NA NA
## 13_1 41 48 53 60 65 67 71 70 71 81 91 96
## 9_1 42 51 59 68 85 96 90 92 93 100 100 98
## 20_1 41 47 54 58 65 73 77 89 98 107 115 117
## 10_1 41 44 52 63 74 81 89 96 101 112 120 124
## 8_1 42 50 61 71 84 93 110 116 126 134 125 NA
## 17_1 42 51 61 72 83 89 98 103 113 123 133 142
## 19_1 43 48 55 62 65 71 82 88 106 120 144 157
## 4_1 42 49 56 67 74 87 102 108 136 154 160 157
## 6_1 41 49 59 74 97 124 141 148 155 160 160 157
## 11_1 43 51 63 84 112 139 168 177 182 184 181 175
## 3_1 43 39 55 67 84 99 115 138 163 187 198 202
## 1_1 42 51 59 64 76 93 106 125 149 171 199 205
## 12_1 41 49 56 62 72 88 119 135 162 185 195 205
## 2_1 40 49 58 72 84 103 122 138 162 187 209 215
## 5_1 41 42 48 60 79 106 141 164 197 199 220 223
## 14_1 41 49 62 79 101 128 164 192 227 248 259 266
## 7_1 41 49 57 71 89 112 146 174 218 250 288 305
## 24_2 42 52 58 74 66 68 70 71 72 72 76 74
## 30_2 42 48 59 72 85 98 115 122 143 151 157 150
## 22_2 41 55 64 77 90 95 108 111 131 148 164 167
## 23_2 43 52 61 73 90 103 127 135 145 163 170 175
## 27_2 39 46 58 73 87 100 115 123 144 163 185 192
## 28_2 39 46 58 73 92 114 145 156 184 207 212 233
## 26_2 42 48 57 74 93 114 136 147 169 205 236 251
## 25_2 40 49 62 78 102 124 146 164 197 231 259 265
## 29_2 39 48 59 74 87 106 134 150 187 230 279 309
## 21_2 40 50 62 86 125 163 217 240 275 307 318 331
## 33_3 39 50 63 77 96 111 137 144 151 146 156 147
## 37_3 41 48 56 68 80 83 103 112 135 157 169 178
## 36_3 39 48 61 76 98 116 145 166 198 227 225 220
## 31_3 42 53 62 73 85 102 123 138 170 204 235 256
## 39_3 42 50 61 78 89 109 130 146 170 214 250 272
## 38_3 41 49 61 74 98 109 128 154 192 232 280 290
## 32_3 41 49 65 82 107 129 159 179 221 263 291 305
## 40_3 41 55 66 79 101 120 154 182 215 262 295 321
## 34_3 41 49 63 85 107 134 164 186 235 294 327 341
## 35_3 41 53 64 87 123 158 201 238 287 332 361 373
## 44_4 42 51 65 86 103 118 127 138 145 146 NA NA
## 45_4 41 50 61 78 98 117 135 141 147 174 197 196
## 43_4 42 55 69 96 131 157 184 188 197 198 199 200
## 41_4 42 51 66 85 103 124 155 153 175 184 199 204
## 47_4 41 53 66 79 100 123 148 157 168 185 210 205
## 49_4 40 53 64 85 108 128 152 166 184 203 233 237
## 46_4 40 52 62 82 101 120 144 156 173 210 231 238
## 50_4 41 54 67 84 105 122 155 175 205 234 264 264
## 42_4 42 49 63 84 103 126 160 174 204 234 269 281
## 48_4 39 50 62 80 104 125 154 170 222 261 303 322
- 而如果使用的是dcast函数,则行名作为两列,有点类似于数据库中的组合主键。
dcast(melt.chick,chick+diet~time)
## chick diet 0 2 4 6 8 10 12 14 16 18 20 21
## 1 18 1 39 35 NA NA NA NA NA NA NA NA NA NA
## 2 16 1 41 45 49 51 57 51 54 NA NA NA NA NA
## 3 15 1 41 49 56 64 68 68 67 68 NA NA NA NA
## 4 13 1 41 48 53 60 65 67 71 70 71 81 91 96
## 5 9 1 42 51 59 68 85 96 90 92 93 100 100 98
## 6 20 1 41 47 54 58 65 73 77 89 98 107 115 117
## 7 10 1 41 44 52 63 74 81 89 96 101 112 120 124
## 8 8 1 42 50 61 71 84 93 110 116 126 134 125 NA
## 9 17 1 42 51 61 72 83 89 98 103 113 123 133 142
## 10 19 1 43 48 55 62 65 71 82 88 106 120 144 157
## 11 4 1 42 49 56 67 74 87 102 108 136 154 160 157
## 12 6 1 41 49 59 74 97 124 141 148 155 160 160 157
## 13 11 1 43 51 63 84 112 139 168 177 182 184 181 175
## 14 3 1 43 39 55 67 84 99 115 138 163 187 198 202
## 15 1 1 42 51 59 64 76 93 106 125 149 171 199 205
## 16 12 1 41 49 56 62 72 88 119 135 162 185 195 205
## 17 2 1 40 49 58 72 84 103 122 138 162 187 209 215
## 18 5 1 41 42 48 60 79 106 141 164 197 199 220 223
## 19 14 1 41 49 62 79 101 128 164 192 227 248 259 266
## 20 7 1 41 49 57 71 89 112 146 174 218 250 288 305
## 21 24 2 42 52 58 74 66 68 70 71 72 72 76 74
## 22 30 2 42 48 59 72 85 98 115 122 143 151 157 150
## 23 22 2 41 55 64 77 90 95 108 111 131 148 164 167
## 24 23 2 43 52 61 73 90 103 127 135 145 163 170 175
## 25 27 2 39 46 58 73 87 100 115 123 144 163 185 192
## 26 28 2 39 46 58 73 92 114 145 156 184 207 212 233
## 27 26 2 42 48 57 74 93 114 136 147 169 205 236 251
## 28 25 2 40 49 62 78 102 124 146 164 197 231 259 265
## 29 29 2 39 48 59 74 87 106 134 150 187 230 279 309
## 30 21 2 40 50 62 86 125 163 217 240 275 307 318 331
## 31 33 3 39 50 63 77 96 111 137 144 151 146 156 147
## 32 37 3 41 48 56 68 80 83 103 112 135 157 169 178
## 33 36 3 39 48 61 76 98 116 145 166 198 227 225 220
## 34 31 3 42 53 62 73 85 102 123 138 170 204 235 256
## 35 39 3 42 50 61 78 89 109 130 146 170 214 250 272
## 36 38 3 41 49 61 74 98 109 128 154 192 232 280 290
## 37 32 3 41 49 65 82 107 129 159 179 221 263 291 305
## 38 40 3 41 55 66 79 101 120 154 182 215 262 295 321
## 39 34 3 41 49 63 85 107 134 164 186 235 294 327 341
## 40 35 3 41 53 64 87 123 158 201 238 287 332 361 373
## 41 44 4 42 51 65 86 103 118 127 138 145 146 NA NA
## 42 45 4 41 50 61 78 98 117 135 141 147 174 197 196
## 43 43 4 42 55 69 96 131 157 184 188 197 198 199 200
## 44 41 4 42 51 66 85 103 124 155 153 175 184 199 204
## 45 47 4 41 53 66 79 100 123 148 157 168 185 210 205
## 46 49 4 40 53 64 85 108 128 152 166 184 203 233 237
## 47 46 4 40 52 62 82 101 120 144 156 173 210 231 238
## 48 50 4 41 54 67 84 105 122 155 175 205 234 264 264
## 49 42 4 42 49 63 84 103 126 160 174 204 234 269 281
## 50 48 4 39 50 62 80 104 125 154 170 222 261 303 322
- margins参数用于为所有的行或者列计算聚合值
#计算每天每组试验小鸡的平均体重
acast(melt.chick,diet~time,fun.aggregate = mean,margins = TRUE)
## 0 2 4 6 8 10 12 14
## 1 41.40 47.25 56.47368 66.78947 79.68421 93.05263 108.5263 123.3889
## 2 40.70 49.40 59.80000 75.40000 91.70000 108.50000 131.3000 141.9000
## 3 40.80 50.40 62.20000 77.90000 98.40000 117.10000 144.4000 164.5000
## 4 41.00 51.80 64.50000 83.90000 105.60000 126.00000 151.4000 161.8000
## (all) 41.06 49.22 59.95918 74.30612 91.24490 107.83673 129.2449 143.8125
## 16 18 20 21 (all)
## 1 144.6471 158.9412 170.4118 177.7500 102.6455
## 2 164.7000 187.7000 205.6000 214.7000 122.6167
## 3 197.4000 233.1000 258.9000 270.3000 142.9500
## 4 182.0000 202.9000 233.8889 238.5556 135.2627
## (all) 168.0851 190.1915 209.7174 218.6889 121.8183
- 也可以只指定计算特定的margins
acast(melt.chick,time~diet,fun.aggregate = mean,margins = 'diet')
## 1 2 3 4 (all)
## 0 41.40000 40.7 40.8 41.0000 41.06000
## 2 47.25000 49.4 50.4 51.8000 49.22000
## 4 56.47368 59.8 62.2 64.5000 59.95918
## 6 66.78947 75.4 77.9 83.9000 74.30612
## 8 79.68421 91.7 98.4 105.6000 91.24490
## 10 93.05263 108.5 117.1 126.0000 107.83673
## 12 108.52632 131.3 144.4 151.4000 129.24490
## 14 123.38889 141.9 164.5 161.8000 143.81250
## 16 144.64706 164.7 197.4 182.0000 168.08511
## 18 158.94118 187.7 233.1 202.9000 190.19149
## 20 170.41176 205.6 258.9 233.8889 209.71739
## 21 177.75000 214.7 270.3 238.5556 218.68889
- subset参数用于选择满足某个条件的记录,使用subset参数需要导入plyr
library(plyr)
acast(melt.chick,time~diet,fun.aggregate = mean,subset = .(diet %in%c(2,3)))
## 2 3
## 0 40.7 40.8
## 2 49.4 50.4
## 4 59.8 62.2
## 6 75.4 77.9
## 8 91.7 98.4
## 10 108.5 117.1
## 12 131.3 144.4
## 14 141.9 164.5
## 16 164.7 197.4
## 18 187.7 233.1
## 20 205.6 258.9
## 21 214.7 270.3
2.2 add_margins
- 不常用,不再介绍。
2.3 cast
- 功能
cast函数有两类,分别为acast和dcast,根据这两个函数的命名规则就可以看出,acast返回的是一个数组(array),而dcast返回的是一个数据框(data frame)。所以,你需要根据你的需求,选择使用哪个函数。该函数的参数介绍如下:
data:一个经过melt的对象,或者一个类似于经过melt的对象。
formula:一个类似于回归的公式,形式为y~x,如果使用的是acast,则y作为行名,x作为列名;如果使用的是dcast,则y是第一列的值,x仍然作为列名。最后,对其他值进行相应的计算。
fun.aggregate:需要使用的聚合函数。
margin:是否对所有的列和行进行聚合计算。
subset:选取一部分子集,选取的方式称为subset = .(variable.name == value)。
fill:对缺失值进行插补的值。
drop:是否保留缺失值的记录。
value.var:存储值的列名。
最常使用的参数为前五个
2.4 colsplit
顾名思义,colsplit函数用于分列,功能与excel的分列类似,该函数有三个参数:
string:一个字符串向量
pattern:正则表达式,用于分割上述字符串
names:分割以后的字符串的列名
该函数返回一个数据框。
str <-c('feng_2017','yang_2013','tang_2012')
nameAndYear <-colsplit(str,"_",c("name","year"))
nameAndYear
## name year
## 1 feng 2017
## 2 yang 2013
## 3 tang 2012
既然提到了分列函数,那么就多介绍一点。tidyr包中的separate包也可以用于分列,并且其功能更加接近excel的功能,可以对一个数据框进行分列。
library(tidyr)
key <-c('3301_A_2017','3301_A_2016','3302_B_2017','3301_B_206')
roomnum <-c(838,866,876,845)
vo <-c(4,4,2,6)
likedata <-data.frame(key,roomnum,vo)
likedata
## key roomnum vo
## 1 3301_A_2017 838 4
## 2 3301_A_2016 866 4
## 3 3302_B_2017 876 2
## 4 3301_B_206 845 6
separate(likedata,key,c('classCode','level','year'),sep = '_')
## classCode level year roomnum vo
## 1 3301 A 2017 838 4
## 2 3301 A 2016 866 4
## 3 3302 B 2017 876 2
## 4 3301 B 206 845 6
2.5 dcast
- 在上述已经有运用,此处不再赘述。
2.6 melt
- 功能
将列名作为行的值,减少列的个数,增加行的个数。比如有如下表格:
## m d pg1 pg2 pg3
## 1 6 1 11.19101 15.23242 12.06216
## 2 6 2 14.41018 16.02994 18.81455
## 3 6 3 19.27001 15.68771 12.29504
## 4 6 4 15.16469 12.88856 18.81050
## 5 6 5 12.59584 12.03740 18.67822
该表格展示的数据是pg1、pg2和pg3三个项目组在6月1至5日每天的完工百分比,单位是%。现在,要求将项目组单独作为一列,其列值为pg1、pg2和pg3,开辟一个新的列用来存储完工百分比。即要求处理后的数据形式为:
## month day pg finished
## 1 "..." "..." "..." "..."
## 2 "..." "..." "..." "..."
## 3 "..." "..." "..." "..."
## 4 "..." "..." "..." "..."
那么,melt函数可以实现上述要求。假设上述表格存储在一个名为volume的数据框中。
melt(volume,id.vars = c('m','d'),variable.name = 'pg',value.name = 'finished')
## m d pg finished
## 1 6 1 pg1 11.19101
## 2 6 2 pg1 14.41018
## 3 6 3 pg1 19.27001
## 4 6 4 pg1 15.16469
## 5 6 5 pg1 12.59584
## 6 6 1 pg2 15.23242
## 7 6 2 pg2 16.02994
## 8 6 3 pg2 15.68771
## 9 6 4 pg2 12.88856
## 10 6 5 pg2 12.03740
## 11 6 1 pg3 12.06216
## 12 6 2 pg3 18.81455
## 13 6 3 pg3 12.29504
## 14 6 4 pg3 18.81050
## 15 6 5 pg3 18.67822
melt(volume,measure.vars = c(3,4,5),variable.name = 'pg',value.name = 'finished')
## m d pg finished
## 1 6 1 pg1 11.19101
## 2 6 2 pg1 14.41018
## 3 6 3 pg1 19.27001
## 4 6 4 pg1 15.16469
## 5 6 5 pg1 12.59584
## 6 6 1 pg2 15.23242
## 7 6 2 pg2 16.02994
## 8 6 3 pg2 15.68771
## 9 6 4 pg2 12.88856
## 10 6 5 pg2 12.03740
## 11 6 1 pg3 12.06216
## 12 6 2 pg3 18.81455
## 13 6 3 pg3 12.29504
## 14 6 4 pg3 18.81050
## 15 6 5 pg3 18.67822
#melt(volume,measure.vars = c('pg1','pg2','pg3'),variable.name = 'pg',value.name = 'finished')
上面两个语句的结果是完全一样的,可以看出,id.vars和measure.vars参数只需要给出其中一个就行了,并且二者是互补的关系。id.vars是不变的列,measure.vars是会变化的列。
2.7 melt.array
- 与melt.data.frame大同小异,不再细说。
2.8 melt.data.frame
- 即上面介绍的melt函数。
2.9 melt.default
- 默认的melt函数,上面已经有介绍。
2.10 melt.list
- 与melt.data.frame大同小异,不再细说。
2.11 melt.matrix
- 与melt.data.frame大同小异,不再细说。
2.12 melt.table
- 与melt.data.frame大同小异,不再细说。
2.13 melt_check
- 功能
检查给melt的输入参数是否正确,输出id.vars和measure.vars。不可显示调用的函数,因此无法演示。
2.14 recast
- 功能
将melt和cast在一个函数里实现。
recast(volume,formula = m~variable,id.var = 1:2)
## Aggregation function missing: defaulting to length
## m pg1 pg2 pg3
## 1 6 5 5 5
由于功能不是那么完善,一般不怎么使用。
- 总结:
reshape2包一般需要掌握melt和cast函数的用法,如果感兴趣,也可以掌握以下colsplit的用法,尤其是tidyr中的separate函数用法。
3.应用实例
3.1 reshape2包的数据
- french fries
str(french_fries)
## 'data.frame': 696 obs. of 9 variables:
## $ time : Factor w/ 10 levels "1","2","3","4",..: 1 1 1 1 1 1 1 1 1 1 ...
## $ treatment: Factor w/ 3 levels "1","2","3": 1 1 1 1 1 1 1 1 1 1 ...
## $ subject : Factor w/ 12 levels "3","10","15",..: 1 1 2 2 3 3 4 4 5 5 ...
## $ rep : num 1 2 1 2 1 2 1 2 1 2 ...
## $ potato : num 2.9 14 11 9.9 1.2 8.8 9 8.2 7 13 ...
## $ buttery : num 0 0 6.4 5.9 0.1 3 2.6 4.4 3.2 0 ...
## $ grassy : num 0 0 0 2.9 0 3.6 0.4 0.3 0 3.1 ...
## $ rancid : num 0 1.1 0 2.2 1.1 1.5 0.1 1.4 4.9 4.3 ...
## $ painty : num 5.5 0 0 0 5.1 2.3 0.2 4 3.2 10.3 ...
head(french_fries)
## time treatment subject rep potato buttery grassy rancid painty
## 61 1 1 3 1 2.9 0.0 0.0 0.0 5.5
## 25 1 1 3 2 14.0 0.0 0.0 1.1 0.0
## 62 1 1 10 1 11.0 6.4 0.0 0.0 0.0
## 26 1 1 10 2 9.9 5.9 2.9 2.2 0.0
## 63 1 1 15 1 1.2 0.1 0.0 1.1 5.1
## 27 1 1 15 2 8.8 3.0 3.6 1.5 2.3
- smiths
str(smiths)
## Classes 'tbl_df', 'tbl' and 'data.frame': 2 obs. of 5 variables:
## $ subject: chr "John Smith" "Mary Smith"
## $ time : num 1 1
## $ age : num 33 NA
## $ weight : num 90 NA
## $ height : num 1.87 1.54
head(smiths)
## # A tibble: 2 x 5
## subject time age weight height
## <chr> <dbl> <dbl> <dbl> <dbl>
## 1 John Smith 1 33 90 1.87
## 2 Mary Smith 1 NA NA 1.54
- tips
str(tips)
## 'data.frame': 244 obs. of 7 variables:
## $ total_bill: num 17 10.3 21 23.7 24.6 ...
## $ tip : num 1.01 1.66 3.5 3.31 3.61 4.71 2 3.12 1.96 3.23 ...
## $ sex : Factor w/ 2 levels "Female","Male": 1 2 2 2 1 2 2 2 2 2 ...
## $ smoker : Factor w/ 2 levels "No","Yes": 1 1 1 1 1 1 1 1 1 1 ...
## $ day : Factor w/ 4 levels "Fri","Sat","Sun",..: 3 3 3 3 3 3 3 3 3 3 ...
## $ time : Factor w/ 2 levels "Dinner","Lunch": 1 1 1 1 1 1 1 1 1 1 ...
## $ size : int 2 3 3 2 4 4 2 4 2 2 ...
head(tips)
## total_bill tip sex smoker day time size
## 1 16.99 1.01 Female No Sun Dinner 2
## 2 10.34 1.66 Male No Sun Dinner 3
## 3 21.01 3.50 Male No Sun Dinner 3
## 4 23.68 3.31 Male No Sun Dinner 2
## 5 24.59 3.61 Female No Sun Dinner 4
## 6 25.29 4.71 Male No Sun Dinner 4
感兴趣的可以利用上述几个数据集进行练习。
3.2 小例子
下面介绍一个美国救助项目的数据,该数据一共包含了8个csv文件(csv可以使用excel查看),每个文件是一个二维表,每个csv有一些共同的部分,比如都是2453行数据,前两列的列名都是一样的,只是对应不同年代会有不同的列数。比如本世纪初就有十年的数据,对应的csv表格的列名如下:
Country.Name:国名
Program.Name:项目名
FY2000:2000年
FY2001:2001年
FY2002:2002年
FY2003:2003年
FY2004:2004年
FY2005:2005年
FY2006:2006年
FY2007:2007年
FY2008:2008年
FY2009:2009年
显然,年份应该是数值,而不应该作为列名,所以我们可以将其整理成整洁数据。同时,对于年份数据,2000我们希望把FY去掉,这样,可以形成时间序列数据。 需要注意的是,我的文件夹下面一共有8个这样的表格,每个表格包含有不同的列数,但是也有一些共同点,我们希望把这8个表格首先进行合并,然后再进行融合。8个表格不算多,我们可以一个一个读取,但是,为了提高工作效率,我们还是创建一个批量读取的函数。
#path为文件夹的位置
batchread <-function(path,sep=",")
{
filepath <-paste(path,'/',dir(path),sep = '')
allfiles <-lapply(filepath,function(x){
read.csv(x,sep = sep)
})
return(allfiles)
}
然后,我们把这8个表格放在一个列表里.
US_Foreign_Aids <-batchread('D:/Rdata/ForeignAid')
现在,US_Foreign_Aid列表里有8个对象,每个对象都是一张二维表,我们将其按列合并。这里需要注意的是,每个表格的前两列都是一个样的,因此在合并的时候只保留一次就行了。
aids <-US_Foreign_Aids[[1]]
for(i in 2:8)
{
this <-US_Foreign_Aids[[i]]
if(length(this) >3)
aids <-cbind(aids,this[,3:length(this)])
else
{
colname <-names(this)[3]
aids <-cbind(aids,this[,3])
names(aids)[length(names(aids))] =colname
}
}
dim(aids)
## [1] 2453 67
names(aids)
## [1] "Country.Name" "Program.Name" "FY2000" "FY2001"
## [5] "FY2002" "FY2003" "FY2004" "FY2005"
## [9] "FY2006" "FY2007" "FY2008" "FY2009"
## [13] "FY2010" "FY1946" "FY1947" "FY1948"
## [17] "FY1949" "FY1950" "FY1951" "FY1952"
## [21] "FY1953" "FY1954" "FY1955" "FY1956"
## [25] "FY1957" "FY1958" "FY1959" "FY1960"
## [29] "FY1961" "FY1962" "FY1963" "FY1964"
## [33] "FY1965" "FY1966" "FY1967" "FY1968"
## [37] "FY1969" "FY1970" "FY1971" "FY1972"
## [41] "FY1973" "FY1974" "FY1975" "FY1976"
## [45] "FY1977" "FY1978" "FY1979" "FY1980"
## [49] "FY1981" "FY1982" "FY1983" "FY1984"
## [53] "FY1985" "FY1986" "FY1987" "FY1988"
## [57] "FY1989" "FY1990" "FY1991" "FY1992"
## [61] "FY1993" "FY1994" "FY1995" "FY1996"
## [65] "FY1997" "FY1998" "FY1999"
现在,aids是一个2453行,67列的大表,前两列是国名和项目名,后面所有的都是时间。
我们使用melt函数,将除了前两列以外的所有列变成值,新列命名为year,值命名为dollar.
aids.melt <-melt(aids,id.vars = 1:2,variable.name = 'year',value.name = 'dollar',na.rm = TRUE)
这步完成以后,需要将年份中的FY去掉,这里有许多方法可以实现,我们选择最简单的一种。
library(stringr)
aids.melt$year<-str_sub(aids.melt$year,3)
head(aids.melt)
## Country.Name Program.Name
## 8 Afghanistan Migration and Refugee Assistance
## 10 Afghanistan Nonproliferation, Anti-Terrorism, Demining and Related
## 11 Afghanistan Other Active Grant Programs
## 12 Afghanistan Other Food Aid Programs
## 18 Afghanistan Title II
## 22 Albania Economic Support Fund/Security Support Assistance
## year dollar
## 8 2000 13952743
## 10 2000 3755316
## 11 2000 2899030
## 12 2000 29581885
## 18 2000 17496891
## 22 2000 15021262
我们还可以按照年份对行进行排序:
library(plyr)
aids.melt.order <-arrange(aids.melt,year)
head(aids.melt.order)
## Country.Name Program.Name year dollar
## 1 Albania Inactive Programs 1946 122378173
## 2 Argentina Inactive Programs 1946 9414
## 3 Asia (not specified) Inactive Programs 1946 9414
## 4 Austria Inactive Programs 1946 619421827
## 5 Belgium Inactive Programs 1946 5648223
## 6 Bolivia Inactive Programs 1946 3765482
上面就是我们最终要的数据了。对此数据可以进行一些分析,比如分析不同国家或者项目接收的资助总额,不同年份的自助总额等。在此不再赘述。