2010-02-02 84 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 
相關問題