R语言小白学习笔记9—数据整理
- 笔记链接
- 学习笔记9—数据整理
- 9.1 cbind和rbind
- 9.2 连接
- 9.3 reshape2
- 9.3.1 melt函数
- 9.3.2 dcast函数
学习笔记9—数据整理
在认真分析数据之前需要花费大量精力操作整理数据。
这章主要函数功能:将数据从面向列转变为面向行、多个数据合并为数据集
主要包:plyr、reshape2和data.table
9.1 cbind和rbind
最简单情况是两个数据集有相同列或相同行,这时可用cbind或rbind函数
例:先用cbind合并几个向量,再用rbind将它们堆积
> sport <- c("Hockey", "Baseball", "Footall")
> league <- c("NHL", "MLB", "NFL")
> trophy <- c("Stanley Cup", "Commissioner's Trophy", "Vince Lombardi Trophy")
> trophies1 <- cbind(sport, league, trophy)
> trophies2 <- data.frame(sport=c("Basketball", "Golf"),
+ league=c("NBA","PGA"),
+ trophy=c("Larry O'Brien Championship Trophy", "Wanamaker Trophy"),
+ stringsAsFactors=FALSE)
> trophies <- rbind(trophies1, trophies2)
9.2 连接
当数据并不是很好地保持一致,以致不能简单地使用cbind时,可以使用merge(基本包)、join(plyr包)以及data.table中的合并功能。
例:将数据连接
1、下载和解压数据
> download.file(url="http://jaredlander.com/data/US_Foreign_Aid.zip", destfile = "E:/B/R/ForeignAid.zip")
> unzip("E:/B/R/ForeignAid.zip", exdir="data")
#这里用unzip解压后我打开文件夹发现没有解压成功,百度查了一下也没有啥解决方法,所以我直接鼠标解压了
2、用for循环,以编程方式加载文件。
用dir得到一个文件列表,遍历文件列表,用assign函数为每一个数据集指定名称。str_sub函数能从字符向量中抽取单个字符
> library(stringr)
> theFiles <- dir("E:/B/R/", pattern = "\\.csv")
> for(a in theFiles)
+ {
+ nameToUse <- str_sub(string=a, start=12, end=18)
+ temp <- read.table(file=file.path("E:/B/R", a),
+ header=TRUE, sep=",",
+ stringsAsFactors = FALSE)
+ assign(x=nameToUse, value=temp)
+ }
3、合并
方法一:
R语言内置函数:meage,用于合并两个数据框
优点:对于每一个数据框可以指定不同的匹配列名
缺点:速度慢
> Aid90s00s <- merge(x=Aid_90s, y=Aid_00s,
+ by.x = c("Country.Name", "Program.Name"),
+ by.y = c("Country.Name", "Program.Name"))
#这里by.x是指定左边数据框的匹配列,by.y是指定右边数据框的匹配列。说白了就是让这两个数据框按着这几列进行匹配。
> head(Aid90s00s)
Country.Name
1 Afghanistan
2 Afghanistan
3 Afghanistan
4 Afghanistan
5 Afghanistan
6 Afghanistan
Program.Name
1 Child Survival and Health
2 Department of Defense Security Assistance
3 Development Assistance
4 Economic Support Fund/Security Support Assistance
5 Food For Education
6 Global Health and Child Survival
FY1990 FY1991 FY1992 FY1993 FY1994 FY1995 FY1996
1 NA NA NA NA NA NA NA
2 NA NA NA NA NA NA NA
3 NA NA NA NA NA NA NA
4 NA NA NA 14178135 2769948 NA NA
5 NA NA NA NA NA NA NA
6 NA NA NA NA NA NA NA
FY1997 FY1998 FY1999 FY2000 FY2001 FY2002 FY2003
1 NA NA NA NA NA 2586555 56501189
2 NA NA NA NA NA 2964313 NA
3 NA NA NA NA 4110478 8762080 54538965
4 NA NA NA NA 61144 31827014 341306822
5 NA NA NA NA NA NA 3957312
6 NA NA NA NA NA NA NA
FY2004 FY2005 FY2006 FY2007 FY2008
1 40215304 39817970 40856382 72527069 28397435
2 45635526 151334908 230501318 214505892 495539084
3 180539337 193598227 212648440 173134034 150529862
4 1025522037 1157530168 1357750249 1266653993 1400237791
5 2610006 3254408 386891 NA NA
6 NA NA NA NA 63064912
FY2009
1 NA
2 552524990
3 3675202
4 1418688520
5 NA
6 1764252
方法二:
plyr中的join
功能:合并数据框
优点:速度快
缺点:每一个表的匹配列名必须一样
例:
> Aid90s00sJoin <- join(x=Aid_90s, y=Aid_00s,
+ by=c("Country.Name", "Program.Name"))
> head(Aid90s00sJoin)
#这里结果和之前相同,我就不放结果了
4、多个合并
现在我们有8个数据框,想把它们合并为一个,而不用一个一个编码合并,这里采用把所有的数据框放进一个列表里,然后用Reduce函数把它们依次合并
例:
(1)、我们用str_sub函数为数据框重新建立一个名字,随后我们构建一个和数据库一样大的空列表,之后给列表取名,用遍历的方式把数据框放进列表
> frameNames <- str_sub(string=theFiles, start=12, end=18)
> frameList <- vector("list", length(frameNames))
> names(frameList) <- frameNames
> for(a in frameNames)
+ {
+ frameList[[a]] <- eval(parse(text=a))
+ }
(2)、用Reduce函数进行循环处理把元素连接起来
> allAid <- Reduce(function(...){
+ join(..., by=c("Country.Name", "Program.Name"))},
+ frameList
+ )
#元素是…意味着任何东西都可以传递给函数
> dim(allAid)
[1] 2453 67
5、合并表
这里我们用data.table中的合并表方法
例:
首先,把数据框转变为表格
> dt90 <- data.table(Aid_90s, key=c("Country.Name", "Program.Name"))
> dt00 <- data.table(Aid_00s, key=c("Country.Name", "Program.Name"))
进行连接
> dt0090 <- dt90[dt00]
这时dt90在左边,采用左连接合并
9.3 reshape2
下一个最常用的需求是融合数据(从列取向变成行取向)或者铸造数据(从行取向变成列取向),这里主要用reshape2包
9.3.1 melt函数
观察Aid_00s数据框,发现每一年数据储存在每一列中,不适合画图。
数据:
> head(Aid_00s,5)
Country.Name
1 Afghanistan
2 Afghanistan
3 Afghanistan
4 Afghanistan
5 Afghanistan
Program.Name
1 Child Survival and Health
2 Department of Defense Security Assistance
3 Development Assistance
4 Economic Support Fund/Security Support Assistance
5 Food For Education
FY2000 FY2001 FY2002 FY2003 FY2004
1 NA NA 2586555 56501189 40215304
2 NA NA 2964313 NA 45635526
3 NA 4110478 8762080 54538965 180539337
4 NA 61144 31827014 341306822 1025522037
5 NA NA NA 3957312 2610006
FY2005 FY2006 FY2007 FY2008 FY2009
1 39817970 40856382 72527069 28397435 NA
2 151334908 230501318 214505892 495539084 552524990
3 193598227 212648440 173134034 150529862 3675202
4 1157530168 1357750249 1266653993 1400237791 1418688520
5 3254408 386891 NA NA NA
所以我们想将其设置为每一行代表一个单独的城市-项目-年,并且把美元金额存在一列。用到melt函数。
> melt00 <- melt(Aid_00s, id.vars = c("Country.Name", "Program.Name"), variable.name = "Year", value.name = "Dollars")
#这里的id.vars参数用来指定哪一列唯一地标识一行
> tail(melt00, 10)
Country.Name
24521 Zimbabwe
24522 Zimbabwe
24523 Zimbabwe
24524 Zimbabwe
24525 Zimbabwe
24526 Zimbabwe
24527 Zimbabwe
24528 Zimbabwe
24529 Zimbabwe
24530 Zimbabwe
Program.Name
24521 Migration and Refugee Assistance
24522 Narcotics Control
24523 Nonproliferation, Anti-Terrorism, Demining and Related
24524 Other Active Grant Programs
24525 Other Food Aid Programs
24526 Other State Assistance
24527 Other USAID Assistance
24528 Peace Corps
24529 Title I
24530 Title II
Year Dollars
24521 FY2009 3627384
24522 FY2009 NA
24523 FY2009 NA
24524 FY2009 7951032
24525 FY2009 NA
24526 FY2009 2193057
24527 FY2009 41940500
24528 FY2009 NA
24529 FY2009 NA
24530 FY2009 174572685
接下来就可以进行作图,分开作图让我们很快就能发现和明白资助每一个项目的趋势
> ggplot(meltAgg, aes(x=Year, y=Dollars)) +
+ geom_line(aes(group=Program.Name)) +
+ facet_wrap(~ Program.Name) +
+ scale_x_continuous(breaks=seq(from=2000, to=2009, by=2)) +
+ theme(axis.text.x=element_text(angle=90, vjust=1,hjust=0)) +
+ scale_y_continuous(labels=multiple_format(extra=dollar, multiple="B"))
(刚开始一直报错,后来发现没加载包:ggplot在ggplot2包里,multiple_format这个函数在useful包里,如果不知道哪个函数在哪个包里边,可以用以下方法:
已安装包且已加载:? function_name
已安装包但未加载:? ?function_name
未安装:sos::findFn(“function_name”)或者百度、谷歌 R function_name(sos包)
方法来自知乎:stone)
9.3.2 dcast函数
接下来我们把融化的数据变回一般的格式。
dcast函数第一个参数是要用的数据,第二个参数是公式,公式左边的列名依然作列,表达式右边的列名变为行,第三个参数是列,代表着公式右边参数的唯一值
> cast00 <- dcast(melt00, Country.Name + Program.Name ~ Year, value.var="Dollars")
> head(cast00)
Country.Name
1 Afghanistan
2 Afghanistan
3 Afghanistan
4 Afghanistan
5 Afghanistan
6 Afghanistan
Program.Name 2000
1 Child Survival and Health NA
2 Department of Defense Security Assistance NA
3 Development Assistance NA
4 Economic Support Fund/Security Support Assistance NA
5 Food For Education NA
6 Global Health and Child Survival NA
2001 2002 2003 2004 2005
1 NA 2586555 56501189 40215304 39817970
2 NA 2964313 NA 45635526 151334908
3 4110478 8762080 54538965 180539337 193598227
4 61144 31827014 341306822 1025522037 1157530168
5 NA NA 3957312 2610006 3254408
6 NA NA NA NA NA
2006 2007 2008 2009
1 40856382 72527069 28397435 NA
2 230501318 214505892 495539084 552524990
3 212648440 173134034 150529862 3675202
4 1357750249 1266653993 1400237791 1418688520
5 386891 NA NA NA
6 NA NA 63064912 1764252