将data.frame的格式从宽改为长

将data.frame的格式从宽改为长,r,dataframe,reshape,r-faq,data.table,tidyr,reshape2,sqldf,R,Dataframe,Reshape,R Faq,Data.table,Tidyr,Reshape2,Sqldf,我很难将我的数据.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 Code Country Year Value AFG

我很难将我的
数据.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
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
现在我想把这个
data.frame
转换成一个长的
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
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()
reformate()
函数 正如一些人在类似问题中提出的那样。 然而,到目前为止,我只得到了混乱的结果

如果可能的话,我想使用
restrape()函数
它看起来更易于处理。

使用重塑包:

#数据
x使用重塑包:

#数据
x
重塑()
需要一段时间才能适应,就像
熔化
/
铸造一样。假设您的数据帧被称为
d
,下面是一个重塑的解决方案:

reshape(d, 
        direction = "long",
        varying = list(names(d)[3:7]),
        v.names = "Value",
        idvar = c("Code", "Country"),
        timevar = "Year",
        times = 1950:1954)
重塑()
需要一段时间才能习惯,就像
熔化
/
铸造
一样。假设您的数据帧被称为
d
,下面是一个重塑的解决方案:

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

三种备选解决方案:

1)带有:

library(tidyr)
long <- wide %>% gather(year, value, -c(Code, Country))
library(reshape2)
long <- melt(wide, id.vars = c("Code", "Country"))
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)
您可以使用与
restrape2
包中相同的
melt
功能(这是一个扩展和改进的实现)<来自
数据的code>melt
。表
还有更多参数,而
melt
功能来自
restrape2
。例如,您还可以指定变量列的名称:

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")
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`)
2)带有:

library(tidyr)
long <- wide %>% gather(year, value, -c(Code, Country))
library(reshape2)
long <- melt(wide, id.vars = c("Code", "Country"))
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)
3)带有:

library(tidyr)
long <- wide %>% gather(year, value, -c(Code, Country))
library(reshape2)
long <- melt(wide, id.vars = c("Code", "Country"))
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)

注:

  • 他退休了。只需进行必要的更改以保持其在起重机上。()
  • 如果要排除
    NA
    值,可以将
    NA.rm=TRUE
    添加到
    melt
    以及
    聚集
    函数中

数据的另一个问题是,值将被R作为字符值读取(由于数字中的
)。您可以使用
gsub
as.numeric
修复该问题:

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

数据:

library(tidyr)
long <- wide %>% gather(year, value, -c(Code, Country))
library(reshape2)
long <- melt(wide, id.vars = c("Code", "Country"))
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)

wide三种备选解决方案:

1)带有:

library(tidyr)
long <- wide %>% gather(year, value, -c(Code, Country))
library(reshape2)
long <- melt(wide, id.vars = c("Code", "Country"))
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)
您可以使用与
restrape2
包中相同的
melt
功能(这是一个扩展和改进的实现)<来自
数据的code>melt
。表
还有更多参数,而
melt
功能来自
restrape2
。例如,您还可以指定变量列的名称:

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")
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`)
2)带有:

library(tidyr)
long <- wide %>% gather(year, value, -c(Code, Country))
library(reshape2)
long <- melt(wide, id.vars = c("Code", "Country"))
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)
3)带有:

library(tidyr)
long <- wide %>% gather(year, value, -c(Code, Country))
library(reshape2)
long <- melt(wide, id.vars = c("Code", "Country"))
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)

注:

  • 他退休了。只需进行必要的更改以保持其在起重机上。()
  • 如果要排除
    NA
    值,可以将
    NA.rm=TRUE
    添加到
    melt
    以及
    聚集
    函数中

数据的另一个问题是,值将被R作为字符值读取(由于数字中的
)。您可以使用
gsub
as.numeric
修复该问题:

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

数据:

library(tidyr)
long <- wide %>% gather(year, value, -c(Code, Country))
library(reshape2)
long <- melt(wide, id.vars = c("Code", "Country"))
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)

wide这里是另一个示例,显示了从
tidyr
中使用
gather
。您可以选择要收集的列
,方法是分别删除它们(就像我在这里所做的那样),或者明确地包括您想要的年份

注意,为了处理逗号(如果未设置
check.names=FALSE
,则添加X),我还使用
dplyr
的mutate与
parse_number
from
readr
将文本值转换回数字。这些都是
tidyverse
的一部分,因此可以与
library(tidyverse)

返回:

   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

下面是另一个示例,演示如何使用来自
tidyr
gather
。您可以选择要收集的列
,方法是分别删除它们(就像我在这里所做的那样),或者明确地包括您想要的年份

注意,为了处理逗号(如果未设置
check.names=FALSE
,则添加X),我还使用
dplyr
的mutate与
parse_number
from
readr
将文本值转换回数字。这些都是
tidyverse
的一部分,因此可以与
library(tidyverse)

返回:

   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

因为这个答案被标记为,所以我觉得分享base R中的另一个选择是有用的:
stack

但是,请注意,
堆栈
不适用于
因子
s——它只适用于
is.vector
is
TRUE
,从
is.vector
的文档中,我们发现:

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

我使用的是样本数据,其中年份列中的值是
factor
s

以下是
堆栈
方法:

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

因为这个答案被标记为,所以我觉得分享base R中的另一个选择是有用的:
stack

但是,请注意,
堆栈
不适用于
因子
s——它只适用于
is.vector
is
TRUE
,从
is.vector
的文档中,我们发现:

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

我使用的是样本数据,其中年份列中的值是
factor
s

以下是
堆栈
方法:

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
这里有一个解决方案:

sqldf("Select Code, Country, '1950' As Year, `1950` As Value From wide
        Union All
       Select Code, Country, '1951' As Year, `1951` As Value From wide
        Union All
       Select Code, Country, '1952' As Year, `1952` As Value From wide
        Union All
       Select Code, Country, '1953' As Year, `1953` As Value From wide
        Union All
       Select Code, Country, '1954' As Year, `1954` As Value From wide;")
要在不键入所有内容的情况下进行查询,可以使用以下命令:

感谢您实施它

不幸的是,我没有