在 R 中使用前缀作为 id 重塑宽到长
reshape wide to long using prefix as id in R
在 R 中,是否可以使用 reshape 函数将数据框从宽整形为长,同时将名称的前缀保留为 id,将后缀保留为列名?
例如,我可能有一个像这样的长数据框:
log_a_mean | b_mean | c_mean | log_a_std | b_std | c_std | log_a_N | b_N | c_N
_______________________________________________________________________________
1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9
我希望将其重塑为:
id | mean | std | N
_____________________________
log_a | 1 | 4 | 7
b | 2 | 5 | 8
c | 3 | 6 | 9
这正是我在当前项目中必须要做的。
我将 reshape2
与 data.table
结合使用。
最后一个包不是必需的,但我已经习惯了它并为它编写了代码(虽然没有太大改变)。
您首先需要做的是一些字符串操作,以便将 id 与实际变量隔离开来。我们将应用的规则是来自输入 table 的变量具有 <id>_<variable>
的形式。 id 可以有下划线,但 variable 不能。基本上,我们会寻找最后一个下划线并从那里切掉。然后,你就把整个东西都投了。
这将是我们的数据集:
d=data.table(
log_a_mean=1,
b_mean=2,
c_mean=3,
log_a_std=4,
b_std=5,
c_std=6,
log_a_N=7,
b_N=8,
c_N=9)
首先,我们将其融化:
d=melt(d,variable.factor=FALSE)
输出如下:
variable value
log_a_mean 1
b_mean 2
... etc.
现在我们拆分变量:
splitvar=function(v){
as.data.frame(
t(sapply(
strsplit(v,"_",fixed=TRUE),
function(x) c(paste(x[1:(length(x)-1)],collapse="_"),x[length(x)])
)),stringsAsFactors=FALSE)
}
d[,c("id","variable"):=splitvar(variable)]
d
的输出现在看起来像
variable value id
mean 1 log_a
mean 2 b
... etc.
铸造它:
d=dcast.data.table(d,id~variable)
d
的输出现在是:
id N mean std
b 8 2 5
c 9 3 6
log_a 7 1 4
我建议你稍微完成一下你的问题,这样你就不会那么快被否决了。这是一个有趣的问题,因为这是一个我偶然发现了几次的问题,所以它对每个人都有用处。但是,很难找到对您格式化问题的兴趣。
使用 data.table
的开发版本,即 v1.9.5
, this could be done easily. You can install it by following these instructions。
melt.data.table
中的这一新功能允许通过提供要连接的列索引,作为 measure.vars
参数的列表单独合并到多个列。
使用@YacineH 的 post 中的 d
:
library(data.table)
# Get prefix of column names
nm1 <- unique(sub('_[^_]+$', '', names(d)))
d.m <- melt(d, measure.vars = list(1:3, 4:6, 7:9),
variable.name="id", value.name=c("mean", "std", "N"))
setattr(d.m$id, 'levels', nm1)
# id mean std N
#1: log_a 1 4 7
#2: b 2 5 8
#3: c 3 6 9
由于 variable
列默认 returns 一个因子列,当它是一个列表时,数字从 1 到 length(measure.vars)
,我们只需将级别替换为 nm1
之后融化。
或者,您可以使用 reshape
来自 base R
#convert the 'data.table' to 'data.frame (if needed)
setDF(d)
#specify direction as 'long' and the column index in a list
#change the 'id' values to 'nm1' and rearrange the columns
d1 <- transform(reshape(d, direction='long',
varying=list(1:3, 4:6, 7:9))[-1], id=nm1)[c(4,1:3)]
#remove the prefix of column names
colnames(d1) <- sub('.*_', '', colnames(d1) )
row.names(d1) <- NULL
d1
# id mean std N
#1 log_a 1 4 7
#2 b 2 5 8
#3 c 3 6 9
您可以从我的 "splitstackshape" 包中尝试 merged.stack
。它需要每行一个唯一的 ID,我刚刚将其添加为 1:nrow(dt)
.
方法是(使用来自@YacineH 的回答的"d"):
library(splitstackshape)
merged.stack(d[, id := 1:nrow(d)], ## Add the id if it doesn't exist
var.stubs = c("mean", "std", "N"), ## Specify the stubs
sep = "var.stubs", ## The sep is just the stubs
atStart = FALSE) ## The stubs are not at the start
# id .time_1 mean std N
# 1: 1 b_ 2 5 8
# 2: 1 c_ 3 6 9
# 3: 1 log_a_ 1 4 7
使用基本的 gsub
删除尾随的“_
”([, .time_1 := gsub("_$", "", .time_1)][]
),您就大功告成了。
在 R 中,是否可以使用 reshape 函数将数据框从宽整形为长,同时将名称的前缀保留为 id,将后缀保留为列名?
例如,我可能有一个像这样的长数据框:
log_a_mean | b_mean | c_mean | log_a_std | b_std | c_std | log_a_N | b_N | c_N
_______________________________________________________________________________
1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9
我希望将其重塑为:
id | mean | std | N
_____________________________
log_a | 1 | 4 | 7
b | 2 | 5 | 8
c | 3 | 6 | 9
这正是我在当前项目中必须要做的。
我将 reshape2
与 data.table
结合使用。
最后一个包不是必需的,但我已经习惯了它并为它编写了代码(虽然没有太大改变)。
您首先需要做的是一些字符串操作,以便将 id 与实际变量隔离开来。我们将应用的规则是来自输入 table 的变量具有 <id>_<variable>
的形式。 id 可以有下划线,但 variable 不能。基本上,我们会寻找最后一个下划线并从那里切掉。然后,你就把整个东西都投了。
这将是我们的数据集:
d=data.table(
log_a_mean=1,
b_mean=2,
c_mean=3,
log_a_std=4,
b_std=5,
c_std=6,
log_a_N=7,
b_N=8,
c_N=9)
首先,我们将其融化:
d=melt(d,variable.factor=FALSE)
输出如下:
variable value
log_a_mean 1
b_mean 2
... etc.
现在我们拆分变量:
splitvar=function(v){
as.data.frame(
t(sapply(
strsplit(v,"_",fixed=TRUE),
function(x) c(paste(x[1:(length(x)-1)],collapse="_"),x[length(x)])
)),stringsAsFactors=FALSE)
}
d[,c("id","variable"):=splitvar(variable)]
d
的输出现在看起来像
variable value id
mean 1 log_a
mean 2 b
... etc.
铸造它:
d=dcast.data.table(d,id~variable)
d
的输出现在是:
id N mean std
b 8 2 5
c 9 3 6
log_a 7 1 4
我建议你稍微完成一下你的问题,这样你就不会那么快被否决了。这是一个有趣的问题,因为这是一个我偶然发现了几次的问题,所以它对每个人都有用处。但是,很难找到对您格式化问题的兴趣。
使用 data.table
的开发版本,即 v1.9.5
, this could be done easily. You can install it by following these instructions。
melt.data.table
中的这一新功能允许通过提供要连接的列索引,作为 measure.vars
参数的列表单独合并到多个列。
使用@YacineH 的 post 中的 d
:
library(data.table)
# Get prefix of column names
nm1 <- unique(sub('_[^_]+$', '', names(d)))
d.m <- melt(d, measure.vars = list(1:3, 4:6, 7:9),
variable.name="id", value.name=c("mean", "std", "N"))
setattr(d.m$id, 'levels', nm1)
# id mean std N
#1: log_a 1 4 7
#2: b 2 5 8
#3: c 3 6 9
由于 variable
列默认 returns 一个因子列,当它是一个列表时,数字从 1 到 length(measure.vars)
,我们只需将级别替换为 nm1
之后融化。
或者,您可以使用 reshape
来自 base R
#convert the 'data.table' to 'data.frame (if needed)
setDF(d)
#specify direction as 'long' and the column index in a list
#change the 'id' values to 'nm1' and rearrange the columns
d1 <- transform(reshape(d, direction='long',
varying=list(1:3, 4:6, 7:9))[-1], id=nm1)[c(4,1:3)]
#remove the prefix of column names
colnames(d1) <- sub('.*_', '', colnames(d1) )
row.names(d1) <- NULL
d1
# id mean std N
#1 log_a 1 4 7
#2 b 2 5 8
#3 c 3 6 9
您可以从我的 "splitstackshape" 包中尝试 merged.stack
。它需要每行一个唯一的 ID,我刚刚将其添加为 1:nrow(dt)
.
方法是(使用来自@YacineH 的回答的"d"):
library(splitstackshape)
merged.stack(d[, id := 1:nrow(d)], ## Add the id if it doesn't exist
var.stubs = c("mean", "std", "N"), ## Specify the stubs
sep = "var.stubs", ## The sep is just the stubs
atStart = FALSE) ## The stubs are not at the start
# id .time_1 mean std N
# 1: 1 b_ 2 5 8
# 2: 1 c_ 3 6 9
# 3: 1 log_a_ 1 4 7
使用基本的 gsub
删除尾随的“_
”([, .time_1 := gsub("_$", "", .time_1)][]
),您就大功告成了。