将dataframe从宽转换为长格式

我有一些麻烦将我的data.frame从宽表转换为长表。 目前看起来像这样:

 wide <- read.table(textConnection( "Code Country 1950 1951 1952 1953 1954 AFG Afghanistan 20,249 21,352 22,532 23,557 24,555 ALB Albania 8,097 8,986 10,058 11,123 12,246"), header=TRUE) 

这产生的数据框架wide如下所示:

 Code Country 1950 1951 1952 1953 1954 AFG Afghanistan 20,249 21,352 22,532 23,557 24,555 ALB Albania 8,097 8,986 10,058 11,123 12,246 

我想变换成一个很长的data.frame例如:

 Code Country Year Value AFG Afghanistan 1950 20,249 AFG Afghanistan 1951 21,352 AFG Afghanistan 1952 22,532 AFG Afghanistan 1953 23,557 AFG Afghanistan 1954 24,555 ALB Albania 1950 8,097 ALB Albania 1951 8,986 ALB Albania 1952 10,058 ALB Albania 1953 11,123 ALB Albania 1954 12,246 

截至2016年,选项包括reshape2::melt() ,以及tidyr::gather()data.table::melt()解决scheme以及旧的reshape::reshape()函数。 然而,到目前为止,我只得到混乱的结果,试图使用这些多个相似,但不同的function。

如果可能的话,我想用reshape()函数来完成它,因为它看起来好一些,但是使用其他软件包的例子/理由是值得赞赏的。

reshape()需要一段时间才能习惯,就像melt / cast 。 这里是一个重塑的解决scheme,假设你的数据框架ID为d

 reshape(d, direction="long", varying=list(names(d)[3:7]), v.names="Value", idvar=c("Code","Country"), timevar="Year", times=1950:1954) 

三种替代scheme:

1: reshape2

 library(reshape2) long <- melt(wide, id.vars = c("Code", "Country")) 

赠送:

  Code Country variable value 1 AFG Afghanistan 1950 20,249 2 ALB Albania 1950 8,097 3 AFG Afghanistan 1951 21,352 4 ALB Albania 1951 8,986 5 AFG Afghanistan 1952 22,532 6 ALB Albania 1952 10,058 7 AFG Afghanistan 1953 23,557 8 ALB Albania 1953 11,123 9 AFG Afghanistan 1954 24,555 10 ALB Albania 1954 12,246 

一些替代符号给出了相同的结果:

 # you can also define the id-variables by column number melt(wide, id.vars = 1:2) # as an alternative you can also specify the measure-variables # all other variables will then be used as id-variables melt(wide, measure.vars = 3:7) melt(wide, measure.vars = as.character(1950:1954)) 

2:用data.table

您可以使用与reshape2包(这是一个扩展和改进的实现)相同的melt函数。 来自data.tablemelt还有更多参数,即meltreshape2 。 你可以例如指定variables列的名称:

 library(data.table) long <- melt(setDT(wide), id.vars=c("Code","Country"), variable.name="year") 

一些备选符号:

 melt(setDT(wide), id.vars = 1:2, variable.name = "year") melt(setDT(wide), measure.vars = 3:7, variable.name = "year") melt(setDT(wide), measure.vars = as.character(1950:1954), variable.name = "year") 

3:随着tidyr

 library(tidyr) long <- wide %>% gather(year, value, -c(Code, Country)) 

一些备选符号:

 wide %>% gather(year, value, -Code, -Country) wide %>% gather(year, value, -1:-2) wide %>% gather(year, value, -1, -2) wide %>% gather(year, value, 3:7) wide %>% gather(year, value, `1950`:`1954`) 

如果你想排除NA值,你可以添加na.rm = TRUE melt以及gatherfunction。


数据的另一个问题是这些值将被R读取为字符值(作为数字的结果)。 你可以用gsubas.numeric来修复:

 long$value <- as.numeric(gsub(",", "", long$value)) 

或者直接使用data.tabledplyr

 # data.table long <- melt(setDT(wide), id.vars = c("Code","Country"), variable.name = "year")[, value := as.numeric(gsub(",", "", value))] # tidyr and dplyr long <- wide %>% gather(year, value, -c(Code,Country)) %>% mutate(value = as.numeric(gsub(",", "", value))) 

数据:

 wide <- read.table(text="Code Country 1950 1951 1952 1953 1954 AFG Afghanistan 20,249 21,352 22,532 23,557 24,555 ALB Albania 8,097 8,986 10,058 11,123 12,246", header=TRUE, check.names=FALSE) 

干得好:

 x <- read.table(textConnection( "Code Country 1950 1951 1952 1953 1954 AFG Afghanistan 20,249 21,352 22,532 23,557 24,555 ALB Albania 8,097 8,986 10,058 11,123 12,246"), header=TRUE) library(reshape) x2 <- melt(x,id=c("Code","Country"),variable_name="Year") x2[,"Year"] <- as.numeric(gsub("X","",x2[,"Year"])) 

这是另外一个例子,显示了从tidyr gather的使用。 您可以通过单独删除它们来select要gather的列(正如我在此处所做的那样),或者通过包括明确指定的年份来gather这些列。

请注意,要处理逗号(如果check.names = FALSE没有设置,则添加X),我还使用dplyr的mutate和parse_numberreadr将文本值转换为数字。 这些都是tidyverse一部分,所以可以与library(tidyverse)一起加载

 wide %>% gather(Year, Value, -Code, -Country) %>% mutate(Year = parse_number(Year) , Value = parse_number(Value)) 

返回:

  Code Country Year Value 1 AFG Afghanistan 1950 20249 2 ALB Albania 1950 8097 3 AFG Afghanistan 1951 21352 4 ALB Albania 1951 8986 5 AFG Afghanistan 1952 22532 6 ALB Albania 1952 10058 7 AFG Afghanistan 1953 23557 8 ALB Albania 1953 11123 9 AFG Afghanistan 1954 24555 10 ALB Albania 1954 12246