根据多列的即时因子求和
Sum by on the fly factor over many columns
我想根据多列的切割值计算总和。
我知道如何为每一列手动执行此操作,但我正在努力寻找一种合适的方法来自动化所有列的功能。通常我会将我的函数与 lapply 一起使用,但我选择与 data.table 一起使用,但我不知道如何使用 char 值。
我希望得到一个 data.table 的列表,其中包含每个类别的总和,或者 matrix/data.table 每个列变量的第一列和以下列作为类别,例如
data.table(col.name=c("v1","v2"), low=c( 1185.3074,1175.7261 ), high=c( 1175.726,350.3937 ))
MWE
rm(list=ls())
if(!require(data.table)) { install.packages("data.table"); require(data.table)}
set.seed(123)
DT<-data.table(v1=runif(50,10,50),v2=runif(50,10,50))
DT[,sum(v1, na.rm = T), by=cut(DT[,v1], breaks=c(0,25,50), labels = c("low", "high"))]
DT[,sum(v2, na.rm = T), by=cut(DT[,v2], breaks=c(0,25,50), labels = c("low", "high"))]
你可以尝试这样的事情,虽然不是你想要的,但结果很接近,它会自动执行摘要过程(本质上它仍然是遍历所有数据列的循环 table 并总结每一个):
DT[, c(lapply(.SD, function(col) tapply(col, cut(col, breaks = c(0, 25, 50)), FUN=sum)),
list(category = c('low', 'high')))]
# v1 v2 category
#1: 323.2453 331.0626 low
#2: 1216.9367 1122.9914 high
我想一种标准方法是重塑两次:
dcast(
melt(DT),
variable ~ cut(value, c(0,25,50), c("low","high")),
fun = sum
)
# variable low high
# 1: v1 323.2453 1216.937
# 2: v2 331.0626 1122.991
melt
重塑为 "long";而 dcast
恢复为 "wide."
有趣的基础 R 解决方案:
do.call(rbind, lapply(DT, function(x) tapply(x, cut(x, 0:2*25), sum)))
# (0,25] (25,50]
#v1 323.2452605 1216.936685
#v2 331.0626328 1122.991399
我从数据 table 开始,但我认为 tidyr 和 dplyr 更适合我以后的目的table。我似乎更容易总结同时使用多个函数同时保持对命名的控制。无论如何,对同一个问题有第二种解决方案总是好的,我需要推动来重塑我的数据。
if(!require(dplyr)) { install.packages("dplyr"); require(dplyr)}
if(!require(tidyr)) { install.packages("tidyr"); require(tidyr)}
DT %>%
gather(variable, value) %>%
mutate(segment = cut(value, c(0,25,50), c("low","high"))) %>%
group_by(variable,segment) %>%
summarise(sum=sum(value)) %>%
spread(segment, sum)
我想根据多列的切割值计算总和。 我知道如何为每一列手动执行此操作,但我正在努力寻找一种合适的方法来自动化所有列的功能。通常我会将我的函数与 lapply 一起使用,但我选择与 data.table 一起使用,但我不知道如何使用 char 值。
我希望得到一个 data.table 的列表,其中包含每个类别的总和,或者 matrix/data.table 每个列变量的第一列和以下列作为类别,例如
data.table(col.name=c("v1","v2"), low=c( 1185.3074,1175.7261 ), high=c( 1175.726,350.3937 ))
MWE
rm(list=ls())
if(!require(data.table)) { install.packages("data.table"); require(data.table)}
set.seed(123)
DT<-data.table(v1=runif(50,10,50),v2=runif(50,10,50))
DT[,sum(v1, na.rm = T), by=cut(DT[,v1], breaks=c(0,25,50), labels = c("low", "high"))]
DT[,sum(v2, na.rm = T), by=cut(DT[,v2], breaks=c(0,25,50), labels = c("low", "high"))]
你可以尝试这样的事情,虽然不是你想要的,但结果很接近,它会自动执行摘要过程(本质上它仍然是遍历所有数据列的循环 table 并总结每一个):
DT[, c(lapply(.SD, function(col) tapply(col, cut(col, breaks = c(0, 25, 50)), FUN=sum)),
list(category = c('low', 'high')))]
# v1 v2 category
#1: 323.2453 331.0626 low
#2: 1216.9367 1122.9914 high
我想一种标准方法是重塑两次:
dcast(
melt(DT),
variable ~ cut(value, c(0,25,50), c("low","high")),
fun = sum
)
# variable low high
# 1: v1 323.2453 1216.937
# 2: v2 331.0626 1122.991
melt
重塑为 "long";而 dcast
恢复为 "wide."
有趣的基础 R 解决方案:
do.call(rbind, lapply(DT, function(x) tapply(x, cut(x, 0:2*25), sum)))
# (0,25] (25,50]
#v1 323.2452605 1216.936685
#v2 331.0626328 1122.991399
我从数据 table 开始,但我认为 tidyr 和 dplyr 更适合我以后的目的table。我似乎更容易总结同时使用多个函数同时保持对命名的控制。无论如何,对同一个问题有第二种解决方案总是好的,我需要推动来重塑我的数据。
if(!require(dplyr)) { install.packages("dplyr"); require(dplyr)}
if(!require(tidyr)) { install.packages("tidyr"); require(tidyr)}
DT %>%
gather(variable, value) %>%
mutate(segment = cut(value, c(0,25,50), c("low","high"))) %>%
group_by(variable,segment) %>%
summarise(sum=sum(value)) %>%
spread(segment, sum)