reshape2是有Hadley Wickham 写的包,可以容易在宽和长两种格式间转换数据。
1. 长宽数据格式
- 宽数据格式
宽数据格式种每个变量对应一列,举例:
## ozone wind temp
## 1 23.61538 11.622581 65.54839
## 2 29.44444 10.266667 79.10000
## 3 59.11538 8.941935 83.90323
## 4 59.96154 8.793548 83.96774
- 长数据格式
没有id(标识)变量,所有度量变量在使用列上;
## variable value
## 1 ozone 23.615385
## 2 ozone 29.444444
## 3 ozone 59.115385
## 4 ozone 59.961538
## 5 wind 11.622581
## 6 wind 10.266667
## 7 wind 8.941935
## 8 wind 8.793548
## 9 temp 65.548387
## 10 temp 79.100000
## 11 temp 83.903226
## 12 temp 83.967742
长格式数据有一列作为可能的变量类型,另一列作为哪些变量的值。长格式不是必须仅有两列,举例,可能有对某年种每天的ozone度量,这时则会增加表示天的列,即有不同长度级别。具体需要什么数据形状依赖你的业务要求。
事实证明,对于某些类型的数据分析,您需要宽格式数据,而对于其他类型的数据,则需要长格式数据。实际应用种,长格式数据较宽格式应用更多,举例,ggplot2需要长格式数据(lm(),glm(),gam()),但对于用户来说宽格式更易阅读。
2. reshape2 包
reshape2主要使用两个关键函数:melt 和 cast:
- melt 把宽格式转成长格式
- cast 把长格式转为宽格式
想象下金属:如果你熔化金属,它会滴下来变长。如果你把它倒入模子里,它就会变宽。
2.1 使用melt函数从宽转为长格式
下面示例使用 airquality 内置数据集。首先改变列名称为小写:
names(airquality) <- tolower(names(airquality))
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
首先我们使用缺省参数运行melt函数会生成什么数据?
aql <- melt(airquality)
## No id variables; using all as measure variables
head(aql)
## variable value
## 1 ozone 41
## 2 ozone 36
## 3 ozone 12
## 4 ozone 18
## 5 ozone NA
## 6 ozone 28
tail(aql)
## variable value
## 913 day 25
## 914 day 26
## 915 day 27
## 916 day 28
## 917 day 29
## 918 day 30
缺省情况下,melt认为所有数值列都是变量值,通常没有问题。但我们现在需要每month的day 下的 ozone, solar.r, wind, 和 temp。这时我们通过id.vars指定month和day,id标识变量是用于标识每行数据。
aql <- melt(airquality, id.vars = c("month", "day"))
head(aql)
## 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
如果需要修改长数据格式列名称,可以使用其他参数:
aql <- melt(airquality, id.vars = c("month", "day"),
variable.name = "climate_variable",
value.name = "climate_value")
head(aql)
## month day climate_variable climate_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
2.2 使用cast函数从长转为宽格式
从宽到长格式转换相当直接,但长到宽稍微有点复杂。除了最简单的情况,它通常涉及一些尝试和错误。下面通过几个示例进行说明。
在reshape2种有多个cast函数。通常遇到最多的数据格式为data.frame对象,首先我们看dcast函数,另外 acast 返回 vector,matrix或array。
让我们把 airquality 转成不同的宽数据格式。首先回复数据格式并使用dcast函数进行转换,比较两者的差异。
dcast 使用公式描述数据形状。参数左边为标识变量,右边是度量变量。
刚开始要想找到正确的公式需要反复尝试并会出错。所以如果你遇到错误时,不要气馁,通常有多种方法可以写出这个公式。
library(reshape2)
aql <- melt(airquality, id.vars = c("month", "day"))
aqw <- dcast(aql, month + day ~ variable)
head(aqw)
## month day ozone solar.r wind temp
## 1 5 1 41 190 7.4 67
## 2 5 2 36 118 8.0 72
## 3 5 3 12 149 12.6 74
## 4 5 4 18 313 11.5 62
## 5 5 5 NA NA 14.3 56
## 6 5 6 28 NA 14.9 66
## 查看原始数据进行对比
head(airquality) # original data
## 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
这里告诉dcast,month和day是标识变量,variable作为度量。因为仅保留有一列,dcast会计算其包含的值列表。我们页可以显示声明 values.var,有些场景必须要如此。
ok,除了顺序不同,我们成功恢复了数据。
如果还没有完全明白,我们可以看下图:
上图描述dcast函数,蓝色底纹表示id标识变量,作为行标识。红色底纹表示将转换为列名的变量,灰色表示要填充至单元格的数据值。
我们在转换数据集实战中通常遇到的错误是每个单元格有超过一个值,举例:我们把ID变量的day变量去掉:
dcast(aql, month ~ variable)
## Aggregation function missing: defaulting to length
## month ozone solar.r wind temp
## 1 5 31 31 31 31
## 2 6 30 30 30 30
## 3 7 31 31 31 31
## 4 8 31 31 31 31
## 5 9 30 30 30 30
运行出现警告:缺少聚集函数。
如果看输出,单元格填充每个月合并数据,我们看到结果显示的月的天数。因此,当转换数据有多个值放入一个单元格时,需要明确如何聚合数据,如,mean,median或sum函数。
2.3 cast函数的聚合参数
下面我们再看一个示例,但这次我们计算平均值,同时指定na.rm=TRUE选项删除NA值:
dcast(aql, month ~ variable, fun.aggregate = mean,
na.rm = TRUE)
## 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
3. 总结
与melt不同,dcast还可以做一些其他有趣的事情,读者可以查看帮助文件进行学习
本文参考链接:https://blog.csdn.net/neweastsun/article/details/120919067