我正在尝试使用 data.table::melt() 函数 reshape (即更长)具有连接变量的数据框。这两个变量都与年份连接。 [注意:我正在使用 data.table 开发版本 (1.14.3)]
library(data.table)
dt <-
data.table(
id = c(1, 2, 3),
varA_2000 = c(2, 6, 1),
varA_2001 = c(1, 1, 1),
varA_2002 = c(1, 2, 3),
varB_2000 = c(1, 0, 1),
varB_2001 = c(1, 1, 1),
varB_2002 = c(0, 0, 0)
)
print(dt)
#> id varA_2000 varA_2001 varA_2002 varB_2000 varB_2001 varB_2002
#> <num> <num> <num> <num> <num> <num> <num>
#> 1: 1 2 1 1 1 1 0
#> 2: 2 6 1 2 0 1 0
#> 3: 3 1 1 3 1 1 0
如何使用melt()函数分离多个串联的列变量,同时使数据帧更长,以便得到这种格式?
desiredDT <- structure(
list(
id = c(1, 2, 3, 1, 2, 3, 1, 2, 3),
year = c(
2020,
2020, 2020, 2021, 2021, 2021, 2022, 2022, 2022
),
varA = c(
2,
6, 1, 1, 1, 1, 1, 2, 3
),
varB = c(1, 0, 1, 1, 1, 1, 0, 0, 0)
),
row.names = c(NA, -9L),
class = c("data.table", "data.frame")
)
head(desiredDT)
#> id year varA varB
#> 1 1 2020 2 1
#> 2 2 2020 6 0
#> 3 3 2020 1 1
#> 4 1 2021 1 1
#> 5 2 2021 1 1
#> 6 3 2021 1 1
此问题与 this 相关就这样。 2014 年,这篇原始文章似乎还没有一个纯粹的 data.table 解决方案。此外,我的日期集涉及制作长多个变量(即 varA 和 varB)。
到目前为止,我已经能够使用两种不同的方法生成我想要的格式(但都需要多个步骤)。
- 方法1(融化,然后使用fcase重新标记变量)。
dx <- melt(dt,
id.vars = "id", measure = patterns("^varA", "^varB"),
value.name = c("varA", "varB"),
variable.name = "year"
)
first_twoStepApproach <- dx[, year := fcase(
year == "1", 2020,
year == "2", 2021,
year == "3", 2022
)]
head(first_twoStepApproach)
#> id year varA varB
#> <num> <num> <num> <num>
#> 1: 1 2020 2 1
#> 2: 2 2020 6 0
#> 3: 3 2020 1 1
#> 4: 1 2021 1 1
#> 5: 2 2021 1 1
#> 6: 3 2021 1 1
- 方法 2(融化,然后在第二步中使用 tstrsplit 拆分变量)
dx <- melt(dt, id.vars = "id", variable.name = c("variable"),
value.name = c("value"),
verbose = TRUE)
#> 'measure.vars' is missing. Assigning all columns other than 'id.vars' columns as 'measure.vars'.
#> Assigned 'measure.vars' are [varA_2000, varA_2001, varA_2002, varB_2000, ...].
dx[, c("variable", "year") := tstrsplit(variable, "_")]
second_twoStepApproach <- dcast(dx, id + year ~ variable, value.name = value)
head(second_twoStepApproach)
#> Key: <id, year>
#> id year varA varB
#> <num> <char> <num> <num>
#> 1: 1 2000 2 1
#> 2: 1 2001 1 1
#> 3: 1 2002 1 0
#> 4: 2 2000 6 0
#> 5: 2 2001 1 1
#> 6: 2 2002 2 0
有没有办法只使用melt()来完成这个转换?
最佳答案
使用pivot_longer
可能会更容易
library(tidyr)
library(dplyr)
pivot_longer(dt, cols = -id, names_to = c(".value", "year"), names_sep = "_")%>%
arrange(year)
-输出
# A tibble: 9 × 4
id year varA varB
<dbl> <chr> <dbl> <dbl>
1 1 2000 2 1
2 2 2000 6 0
3 3 2000 1 1
4 1 2001 1 1
5 2 2001 1 1
6 3 2001 1 1
7 1 2002 1 0
8 2 2002 2 0
9 3 2002 3 0
或者通过data.table
,使用measure.vars
library(data.table)
melt(dt, measure.vars = measure(value.name, year, sep = "_"))
-输出
id year varA varB
<num> <char> <num> <num>
1: 1 2000 2 1
2: 2 2000 6 0
3: 3 2000 1 1
4: 1 2001 1 1
5: 2 2001 1 1
6: 3 2001 1 1
7: 1 2002 1 0
8: 2 2002 2 0
9: 3 2002 3 0
关于r - 在两个或多个变量上使用 Melt() 时,如何保留串联变量的两个部分? (数据.表::熔化()),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/72956632/