我希望能够在 data.table
中同时使用汇总函数和标准表达式发现c()
效果很好,但它将因子强制转换为整数表示形式。
data.table
有没有简单的方法我可以使用命名列表摘要和带有因子值的摘要,并保留实际因子类而不将其转换为整数?
library(data.table)
library(lubridate)
data <- data.table(date = ymd("2019-07-07","2018-05-04",
"2019-08-09","2017-06-03"),
colour = factor(c("red","blue","green","yellow")),
group = factor(c("A","B","A","B")),
value1 = c(5,23,3,1),
value2 = c(3,2,4,1))
summary_func <- function(x, var_name){
setNames(list(mean(x),
sd(x)), paste0(var_name,"_",c("mean","sd")))
}
data[,c(summary_func(value1,var_name = "val1"),
summary_func(value2,var_name = "val2"),
first_colour = colour[1]),
by = group]
结果:
group val1_mean val1_sd val2_mean val2_sd first_colour
1: A 4 1.414214 3.5 0.7071068 3
2: B 12 15.556349 1.5 0.7071068 1
我希望结果是:
group val1_mean val1_sd val2_mean val2_sd first_colour
1: A 4 1.414214 3.5 0.7071068 green
2: B 12 15.556349 1.5 0.7071068 red
我在下面取得了一些成功,但这些解决方案非常不优雅,我怀疑不是很通用。因此,我希望有一个更简洁的data.table
解决这个问题的方法。
我尝试过的事情:
- 我发现我可以通过使用
list()
来实现结果围绕列表摘要,并给它们一个非常具体的命名约定("SF"
)。然后,您需要将列排序为列表列和非列表列,然后使用cbind
,lapply
,和rbindlist
将列表强制到 data.tables 中。然后,您必须重命名结果列。
tmp1 <- data[,.(first_colour = colour[1],
SF1 = list(summary_func(value1, "val1")),
SF2 = list(summary_func(value2, "val2"))),
by = group]
list_cols <- names(which(sapply(tmp1,is.list)))
grp_cols <- names(tmp1)[!names(tmp1) %in% list_cols]
tmp2 <- tmp1[, do.call(cbind,
c(lapply(mget(list_cols),rbindlist),
deparse.level = 0)), by = grp_cols]
setnames(tmp2, gsub("^SF\\d\\.", "", names(tmp2)))
tmp2
- 我发现如果您创建
c()
的替代版本你可以获得所需的行为。您需要以特定方式解压参数以保留类型和名称。我认为相对于c()
来说这可能会非常慢和list()
因为这两个函数都是基元函数,因此基于编译的 C 代码。
c_alt <- function(...){
blah <- list(...)
result <- list()
for(i in 1:length(blah)){
len <- length(blah[[i]])
for(j in 1:len){
result[[length(result) + 1]] <- blah[[i]][[j]]
}
if(len > 1){
names(result)[(length(result)-len):length(result)] <- names(blah[[i]])
}else{
names(result)[[length(result)]] <- names(blah)[[i]]
}
}
result
}
data[,c_alt(summary_func(value1,var_name = "val1"),
summary_func(value2,var_name = "val2"),
first_colour = colour[1]),
by = group]
最佳答案
一种方法是将颜色
转换为字符,提取第一个值并在需要时再次使其因子
。
library(data.table)
data[,c(summary_func(value1,var_name = "val1"),
summary_func(value2,var_name = "val2"),
first_colour = as.character(colour[1])),
by = group][, first_colour := factor(first_colour)][]
# group val1_mean val1_sd val2_mean val2_sd first_colour
#1: A 4 1.414214 3.5 0.7071068 red
#2: B 12 15.556349 1.5 0.7071068 blue
关于r - 使用 `data.table` 和 `c()` 进行汇总时可以防止因子强制吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/68451831/