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

上面就是我们最终要的数据了。对此数据可以进行一些分析,比如分析不同国家或者项目接收的资助总额,不同年份的自助总额等。在此不再赘述。

posted @ 2017-11-09 14:45  小肥羊的博客  阅读(976)  评论(0编辑  收藏  举报