所谓数据整形,所简单点就是改变数据的摆放形式,下面我们要讲一个很重要的数据整形方式,它几乎和透视表一样重要,即long型和wide型数据表变换。之所以这么强调其重要性,首先在数据分析中经常用到,另外R的基础做图和ggpot2做图所需要的数据是不一样的,对于 base R 来说,wide型数据更适合,而对于 ggplot2,则long 型比较方便,为什么是这样?你可以私信 Hadley Wickham了解。
我们首先认识一下long 型和wide 型数据的区别。
datawide <- read.csv("E:/业余/zimeiti/窥视数据背后的逻辑:基于R与python/bookwriting/第二章数据探索招招都是利器/data/datawide.csv",
header = T, sep = ",", stringsAsFactors = F)
head(datawide)
上面产生的数据框即可称之为wide型数据,第一列省份,其实它的后4列可以合并成一列作为医院等级,然后再将数值合并成一列作为总收入就变成了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型之间的转换。
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行。
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参数的指定,但是这时你一定要保证数据没有出现上述重复现象,否则我们看一下它们的区别:
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
友情链接