北京字典价格联盟

你能给数据做次整形手术吗:long型和wide型

只看楼主 收藏 回复
  • - -
楼主
好主意值得扩散,激发我们创造的动力


所谓数据整形,所简单点就是改变数据的摆放形式,下面我们要讲一个很重要的数据整形方式,它几乎和透视表一样重要,即long型和wide型数据表变换。之所以这么强调其重要性,首先在数据分析中经常用到,另外R的基础做图和ggpot2做图所需要的数据是不一样的,对于 base R 来说,wide型数据更适合,而对于 ggplot2,则long 型比较方便,为什么是这样?你可以私信 Hadley Wickham了解。
我们首先认识一下long 型和wide 型数据的区别。

wide型表
datawide <- read.csv("E:/业余/zimeiti/窥视数据背后的逻辑:基于R与python/bookwriting/第二章数据探索招招都是利器/data/datawide.csv", 
                  header = T, sep = ",", stringsAsFactors = F)
head(datawide)

上面产生的数据框即可称之为wide型数据,第一列省份,其实它的后4列可以合并成一列作为医院等级,然后再将数值合并成一列作为总收入就变成了long型数据。合并后结果如下:

long型表
datalong <- read.csv("E:/业余/zimeiti/窥视数据背后的逻辑:基于R与python/bookwriting/第二章数据探索招招都是利器/data/datalong.csv", 
                  header = T, sep = ",", stringsAsFactors = F)
head(datalong)

long型把wide型的最后4列的列名组成了一个新的列,作为医院级别,然后相应的数值组成了另一列,作为总收入,数据变长了。这就是long型与wide型的区别,这种数据之间的变换很常见,是数据整形的必备技能之一。我比较常用的转换包为reshape2,这个包里的两个函数melt函数和dcast函数分别对应以上任务。下面以上面两个数据框为例进行wide型与long型之间的转换。

wide型转化为long型
library(reshape2)
temp <- melt(data = datawide, id.vars = c("省份"), 
                 measure.vars = c("二级", "三级", "未评级", "一级"),
                 variable.name = "医院级别", value.name = "总收入")
head(temp)
temp <- melt(datawide, id.vars = c("省份"), variable.name = "医院级别", 
             value.name = "总收入")

查看一下数据框temp和我们之前的datalong就发现一模一样了,reshape2包中的melt函数就是将wide型数据转化为long型数据,顾名思义melt就是融合的意思。第一个参数为将要转化的数据框,参数id.vars用来指定id列,所谓id列就是保持原来的排列方式不改变的那些列,比如我们希望”省份”保持原来的位置,它可以是一个向量,需要保持更多列不变,在后面添加就是了;measure.vars指定要融合的列,variable.name用来指定融合后的分类变量列的名字,我们这里取名为医院级别;value.name用来指定融合后的数值列的名称,这里取名为总收入,这样一个函数就完成了这次从wide到long的整形;有时候我们会除了保留id列不变以外,其他列统统融合,这样在measure.vars一个一个的写出列名就比较麻烦,这种情况可以不指定measure.vars,默认表示去除id列以外数据框的其他列都参与融合,如4行。

long型转化为wide型
temp <- dcast(data = datalong, formula = 省份 ~ 医院级别, value.var = "总收入", fun.aggregate = sum)
head(temp)

可以看到temp就由long型转化为和datawide一模一样的wide型数据了,dcast函数指的是data.frame casting的意思,即数据框转换,第一个参数data指定将要转化的数据框;第二个参数formula是一个表达式,前半部为id列,就是那些保持原来位置不变的列,如果需要添加多个id列就用加号隔开如“省份 + 城市”,后半部是要差分的分类列,一般只有一列,前后用表达式分割符~分割开;value.var参数指定要差分的数值列,fun.aggregate指定数据透视的函数,即指定如果出现分类变量相同的数据,其value值怎么计算,这样就完成了从long型到wide型的延展。

另外在进行long型转wide型时,可能会只选择一到两个id列,而不是选择所有的id列保持不变,数据有可能出现重复行,比如下面的数据:

dcastfun <- read.csv("E:/业余/zimeiti/窥视数据背后的逻辑:基于R与python/bookwriting/第二章数据探索招招都是利器/data/dcastfun.csv", 
                  header = T, sep = ",", stringsAsFactors = F)
head(dcastfun)

如果只选择省份这一列作为id列,那北京+二级就会出现两次,那dcast函数就要知道怎么计算这两条数据,是进行加减乘除等等哪一种?很多伙计写代码时包括我自己都会省略fun.aggregate参数的指定,但是这时你一定要保证数据没有出现上述重复现象,否则我们看一下它们的区别:

注意指定function
nofun <- dcast(dcastfun,  省份 ~ 医院级别, value.var = "总收入") 
# Aggregation function missing: defaulting to length
head(nofun)
havefun <- dcast(dcastfun,  省份 ~ 医院级别, value.var = "总收入", fun.aggregate = sum)
head(havefun)

我们发现上面两句的结果截然不同,所以当你指定的id列不能保证每一行都是独一无二的时,这时就存在一个透视表的问题,你是要计数,还是要求和,还是要求均值,需要通过fun.aggregate指定一个透视函数,如果不指定就默认为计数函数,即length,如第一句,它统计的不是北京医院二级医院的总收入,而是北京二级在表中出现的次数;3句我们制定了透视函数为sum,这样北京二级医院就按照求和的方式汇总了。

对于高级语言,如果你没有了解每一个参数的意义,那函数执行完了之后一定要检查结果是不是你要的。

数据连接:http://pan.baidu.com/s/1dEK2Hod

好主意值得扩散,激发我们创造的动力,非常感谢花粉传播者

关于我们
关注理性与文艺,用数据创作内容性的精致阅读,更多资料分享添加qq群。
交流QQ:549041728
QQ交流群1:105646151(人满收费)
QQ交流群2:528749057
微信号:大音如霜


举报 | 1楼 回复

友情链接