2016-09-19 58 views
0

我想根據幾列的截斷值計算總和。 我知道如何爲每列手動執行此操作,但我正在努力尋找一種體面的方法來自動化所有列的功能。通常我會用lapply來使用我的函數,但是我選擇使用data.table來完成,而我無法弄清楚如何使用char值。通過飛行因素求和多列

我希望的與總和爲每個類別或基質/ data.table有用於每列變量的第一列和下面的列作爲類別data.tables的列表,像

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"))] 

回答

3

我想一個標準的方式是重塑兩次:

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重塑爲 「長」;而dcast恢復爲「寬」。

1

你可以嘗試這樣的事情,不是你想要的,雖然,但結果是接近,它可以自動彙總過程到底是什麼(本質上它仍然是一個遍歷數據表中的所有列和彙總每個人):

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 
1

爲了好玩基礎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 
0

我開始用數據表,但我認爲tidyr和dplyr更適合我後來的目的。在保持對命名的控制的同時,我似乎更容易同時使用多個功能進行總結。無論如何,對同樣的問題採取第二種解決方案總是很好,我需要微調來重塑我的數據。

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)