在 R 中重塑此数据框的最简单方法?
Easiest way to reshape this dataframe in R?
假设我有以下 wide/messy 数据框:
df1 <- data.frame(ID = c(1, 2), Gender = c("M","F"),
Q1 = c(1, 5), Q2 = c(2, 6),
Q3 = c(3, 7), Q4 = c(4, 8))
ID Gender Q1 Q2 Q3 Q4
1 M 1 2 3 4
2 F 5 6 7 8
我怎样才能把它变成这个数据框:
df2 <- data.frame(ID = c(1, 1, 2, 2), Gender = c("M", "M", "F", "F"),
V1 = c(1, 3, 5, 7), V2 = c(2, 4, 6, 8))
ID Gender V1 V2
1 M 1 2
1 M 3 4
2 F 5 6
2 F 7 8
我知道有多个包和函数(例如 tidyr、reshape2、reshape 函数)可以完成此操作。哪种方法最简单,怎么做?非常感谢任何人可以提供的任何帮助。谢谢!
您可以尝试 data.table
的开发版本 melt
,即 v1.9.5
。它可以将 measure.vars
中的多个变量作为一个列表。安装开发版本的说明是here
library(data.table)#v1.9.5+
melt(setDT(df1), measure.vars=list(c(3,5), c(4,6)),
value.name=c('V1', 'V2'))[,variable:=NULL][order(ID)]
# ID Gender V1 V2
#1: 1 M 1 2
#2: 1 M 3 4
#3: 2 F 5 6
#4: 2 F 7 8
或使用 reshape
来自 base R
res <- subset(reshape(df1, idvar=c('ID', 'Gender'),
varying=list(c(3,5), c(4,6)), direction='long'), select=-time)
row.names(res) <- NULL
更新
如果我们需要将 'df2' 转换回 'df1',可以使用 data.table
的 dcast
。它可以包含多个 value.var
列。在进行dcast
之前,我们需要按组('ID'、'Gender')创建一个序列列(N
)
dcast(setDT(df2)[, N:=1:.N, list(ID, Gender)], ID+Gender~N,
value.var=c('V1', 'V2'))
# ID Gender 1_V1 2_V1 1_V2 2_V2
#1: 1 M 1 3 2 4
#2: 2 F 5 7 6 8
或者我们使用 ave
按组创建一个序列,然后使用 base R
中的 reshape
。
df2 <- transform(df2, N= ave(seq_along(ID), ID, Gender, FUN=seq_along))
reshape(df2, idvar=c('ID', 'Gender'), timevar='N', direction='wide')
# ID Gender V1.1 V2.1 V1.2 V2.2
#1 1 M 1 2 3 4
#3 2 F 5 6 7 8
数据
df1 <- data.frame(ID = c(1, 2), Gender = c("M","F"), Q1 = c(1, 5),
Q2 = c(2, 6), Q3 = c(3, 7), Q4 = c(4, 8))
df2 <- data.frame(ID = c(1, 1, 2, 2), Gender = c("M", "M", "F", "F"),
V1 = c(1, 3, 5, 7), V2 = c(2, 4, 6, 8))
假设我有以下 wide/messy 数据框:
df1 <- data.frame(ID = c(1, 2), Gender = c("M","F"),
Q1 = c(1, 5), Q2 = c(2, 6),
Q3 = c(3, 7), Q4 = c(4, 8))
ID Gender Q1 Q2 Q3 Q4
1 M 1 2 3 4
2 F 5 6 7 8
我怎样才能把它变成这个数据框:
df2 <- data.frame(ID = c(1, 1, 2, 2), Gender = c("M", "M", "F", "F"),
V1 = c(1, 3, 5, 7), V2 = c(2, 4, 6, 8))
ID Gender V1 V2
1 M 1 2
1 M 3 4
2 F 5 6
2 F 7 8
我知道有多个包和函数(例如 tidyr、reshape2、reshape 函数)可以完成此操作。哪种方法最简单,怎么做?非常感谢任何人可以提供的任何帮助。谢谢!
您可以尝试 data.table
的开发版本 melt
,即 v1.9.5
。它可以将 measure.vars
中的多个变量作为一个列表。安装开发版本的说明是here
library(data.table)#v1.9.5+
melt(setDT(df1), measure.vars=list(c(3,5), c(4,6)),
value.name=c('V1', 'V2'))[,variable:=NULL][order(ID)]
# ID Gender V1 V2
#1: 1 M 1 2
#2: 1 M 3 4
#3: 2 F 5 6
#4: 2 F 7 8
或使用 reshape
来自 base R
res <- subset(reshape(df1, idvar=c('ID', 'Gender'),
varying=list(c(3,5), c(4,6)), direction='long'), select=-time)
row.names(res) <- NULL
更新
如果我们需要将 'df2' 转换回 'df1',可以使用 data.table
的 dcast
。它可以包含多个 value.var
列。在进行dcast
N
)
dcast(setDT(df2)[, N:=1:.N, list(ID, Gender)], ID+Gender~N,
value.var=c('V1', 'V2'))
# ID Gender 1_V1 2_V1 1_V2 2_V2
#1: 1 M 1 3 2 4
#2: 2 F 5 7 6 8
或者我们使用 ave
按组创建一个序列,然后使用 base R
中的 reshape
。
df2 <- transform(df2, N= ave(seq_along(ID), ID, Gender, FUN=seq_along))
reshape(df2, idvar=c('ID', 'Gender'), timevar='N', direction='wide')
# ID Gender V1.1 V2.1 V1.2 V2.2
#1 1 M 1 2 3 4
#3 2 F 5 6 7 8
数据
df1 <- data.frame(ID = c(1, 2), Gender = c("M","F"), Q1 = c(1, 5),
Q2 = c(2, 6), Q3 = c(3, 7), Q4 = c(4, 8))
df2 <- data.frame(ID = c(1, 1, 2, 2), Gender = c("M", "M", "F", "F"),
V1 = c(1, 3, 5, 7), V2 = c(2, 4, 6, 8))