2010-02-02 94 views
77

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

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转变成一个长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 

我已经看过,并与melt()reshape()功能 一些人建议对类似的问题试过了。 但是,到目前为止,我只得到凌乱的结果。

如果可能的话,我想用reshape()函数来做,因为 它看起来有点更好处理。

+1

不知道如果是这样的问题,但在重塑包的功能是熔体铸造 – 2010-02-02 17:51:33

+0

而重塑包已被取代reshape2。 – 2014-09-16 00:10:34

+2

现在,reshape2已被tidyr取代。 – drhagen 2016-02-15 13:37:36

回答

54

reshape()需要一段时间去适应,就像melt/cast。这里是重塑一个解决方案,假设你的数据帧被称为d

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

使用重塑包:

#data 
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"])) 
64

三种可供选择的解决方案:

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

可以使用相同melt功能如reshape2包(其是一个扩展&改进的实现)。 melt from data.table也有更多参数melt from reshape2。您可以的exaple还指定了可变列的名称:

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, -1, -2) 
wide %>% gather(year, value, 3:7) 
wide %>% gather(year, value, `1950`:`1954`) 

如果你想排除NA值,你可以添加na.rm = TRUEmelt还有gather功能。


与所述数据的另一个问题是,该值将由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) 
+0

很好的答案,只需再提一点小小的提示:除了'id'和'time'之外,不要在数据框中加入任何变量,'melt'不能告诉你在这种情况下要做什么。 – 2017-10-19 11:11:14

+1

@JasonGoal你能详细说明一下吗?正如我在解释你的评论,这不应该是一个问题。只需指定'id.vars'和'measure.vars'。 – Jaap 2017-10-19 11:55:24

+0

,那对我很好,不知道'id.vars'和'measure.vars'可以在第一个选项中指定,对不起,我的错。 – 2017-10-20 05:34:26

1

下面是另一个例子展示使用gather from tidyr。您可以通过单独删除它们来选择gather的列(正如我在此处所做的那样),或者通过包括明确指定的年份来选择列。

需要注意的是,处理逗号(,如果check.names = FALSE未设置X的增加),我也使用dplyr的与parse_number变异从readr到文本值转换回数字。这些都是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 
3

由于这个答案被打上,我认为这将是从分享另一种选择有用基地R:stack

但是请注意,这stackfactor的工作 - 如果is.vectorTRUE,并从文档is.vector它才能正常运行,我们发现:

is.vector回报TRUE如果x是一个除了名称以外,没有属性的指定模式的向量。否则返回FALSE

我使用样本数据from @Jaap's answer,其中年份列中的值为factor s。

这里的stack方法:(重铸)

cbind(wide[1:2], stack(lapply(wide[-c(1, 2)], as.character))) 
## Code  Country values ind 
## 1 AFG Afghanistan 20,249 1950 
## 2 ALB  Albania 8,097 1950 
## 3 AFG Afghanistan 21,352 1951 
## 4 ALB  Albania 8,986 1951 
## 5 AFG Afghanistan 22,532 1952 
## 6 ALB  Albania 10,058 1952 
## 7 AFG Afghanistan 23,557 1953 
## 8 ALB  Albania 11,123 1953 
## 9 AFG Afghanistan 24,555 1954 
## 10 ALB  Albania 12,246 1954 
相关问题