两种替代方案:
1) 使用 data.table:
您可以使用 melt
函数:
library(data.table)
long <- melt(setDT(wide), id.vars = c("Code","Country"), variable.name = "year")
这将会给出:
> long
Code Country year 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
一些备选符号表示:
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")
2) 使用 tidyr:
使用 pivot_longer()
:
library(tidyr)
long <- wide %>%
pivot_longer(
cols = `1950`:`1954`,
names_to = "year",
values_to = "value"
)
注意:
names_to
和 values_to
默认为分别为"name"
和 "value"
,因此您可以将其简写为wide %>% pivot_longer(`1950`:`1954`)
。
cols
参数使用高度灵活的tidyselect DSL,因此您可以使用否定选择(!c(Code, Country)
),选择帮助器(starts_with("19")
; matches("^\\d{4}$")
),数字索引(3:7
)等来选择相同的列。
tidyr::pivot_longer()
是 tidyr::gather()
和 reshape2::melt()
的继承者,后两者已不再开发。
转换值
数据的另一个问题是数值将被R读取为字符值(由于数字中的,
)。您可以在重塑之前使用gsub
和as.numeric
进行修复:
long$value <- as.numeric(gsub(",", "", long$value))
或在使用 data.table
或 tidyr
进行重塑时:
long <- melt(setDT(wide),
id.vars = c("Code","Country"),
variable.name = "year")[, value := as.numeric(gsub(",", "", value))]
long <- wide %>%
pivot_longer(
cols = `1950`:`1954`,
names_to = "year",
values_to = "value",
values_transform = ~ as.numeric(gsub(",", "", .x))
)
数据:
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)
tidyr
包中的gather
和spread
函数已经被pivot_*
函数所取代。 - NelsonGon