基于使用列的累积和创建的分组筛选R data.table
我需要一个高效的data.table解决方案来过滤一列的累积和中的每300个的第一个和最后一个实例。我真正的数据集是数百万行,所以我不是在寻找循环解决方案基于使用列的累积和创建的分组筛选R data.table,r,filter,data.table,cumsum,R,Filter,Data.table,Cumsum,我需要一个高效的data.table解决方案来过滤一列的累积和中的每300个的第一个和最后一个实例。我真正的数据集是数百万行,所以我不是在寻找循环解决方案 #Example data: dt <- data.table(idcolref=c(1:1000),y=rep(10,1000)) #示例数据: dt我想我已经正确地解释了您的要求: 要计算向量(列)的累积和 如果累计总和达到300,您希望将其重置回0 每次重置为0时,您都希望表示向量的这些值在一个新组中 您希望选择每个组的第一
#Example data:
dt <- data.table(idcolref=c(1:1000),y=rep(10,1000))
#示例数据:
dt我想我已经正确地解释了您的要求:
要计算向量(列)的累积和李>
如果累计总和达到300,您希望将其重置回0李>
每次重置为0时,您都希望表示向量的这些值在一个新组中
您希望选择每个组的第一行和最后一行
如果是这种情况,您可以在Rcpp
library(data.table)
dt <- data.table(x=rep(5,1e7),y=rep(10,1e7))
## adding a row index to keep track of which rows are returned
dt[, id := .I]
library(Rcpp)
cppFunction('Rcpp::NumericVector findGroupRows(Rcpp::NumericVector x) {
int cumsum = 0;
int grpCounter = 0;
size_t n = x.length();
Rcpp::NumericVector groupedCumSum(n);
for ( size_t i = 0; i < n; i++) {
cumsum += x[i];
if (cumsum > 300) {
cumsum = 0;
grpCounter++;
}
groupedCumSum[i] = grpCounter;
}
return groupedCumSum;
}')
dt[, grp := findGroupRows(y)]
dt[ dt[, .I[c(1, .N)], by = grp]$V1]
库(data.table)
dt我想我已经正确地解释了您的要求:
要计算向量(列)的累积和李>
如果累计总和达到300,您希望将其重置回0李>
每次重置为0时,您都希望表示向量的这些值在一个新组中
您希望选择每个组的第一行和最后一行
如果是这种情况,您可以在Rcpp
library(data.table)
dt <- data.table(x=rep(5,1e7),y=rep(10,1e7))
## adding a row index to keep track of which rows are returned
dt[, id := .I]
library(Rcpp)
cppFunction('Rcpp::NumericVector findGroupRows(Rcpp::NumericVector x) {
int cumsum = 0;
int grpCounter = 0;
size_t n = x.length();
Rcpp::NumericVector groupedCumSum(n);
for ( size_t i = 0; i < n; i++) {
cumsum += x[i];
if (cumsum > 300) {
cumsum = 0;
grpCounter++;
}
groupedCumSum[i] = grpCounter;
}
return groupedCumSum;
}')
dt[, grp := findGroupRows(y)]
dt[ dt[, .I[c(1, .N)], by = grp]$V1]
库(data.table)
dt仅使用数据的简单解决方案。表
和基本R函数:
dt[, grp2 := (cumsum(y) - 1) %/% 300]
# straight forward solution:
dt[, .SD[c(1, .N)], by = "grp"]
# more efficient for large datasets, as suggested by SymbolixAU
dt[ dt[, .I[c(1, .N)], by = "grp"]$V1]
# check if your groups are of the correct size
table(dt[, .N[[1]], by = "grp"]$V1)
%/%
是整数除法运算符
.SD
是按组划分的数据表的当前子集
.N
是当前行中的行数
子集(与nrow(.SD
)相同)
-1
确保第一组的大小正确
仅使用数据的简单解决方案。表
和基本R函数:
dt[, grp2 := (cumsum(y) - 1) %/% 300]
# straight forward solution:
dt[, .SD[c(1, .N)], by = "grp"]
# more efficient for large datasets, as suggested by SymbolixAU
dt[ dt[, .I[c(1, .N)], by = "grp"]$V1]
# check if your groups are of the correct size
table(dt[, .N[[1]], by = "grp"]$V1)
%/%
是整数除法运算符
.SD
是按组划分的数据表的当前子集
.N
是当前行中的行数
子集(与nrow(.SD
)相同)
-1
确保第一组的大小正确
x是您的组?不,我需要根据x(或y)生成组。您能更清楚地说,哪一列是您的id列吗?您确定您的dt.所需的正确吗?如果在dt[,id:=.I]
上放置索引列,则表明第一组是第1行和第122行?为什么输出的第一个值为0?应该是10吗?x是您的组吗?不,我需要根据x(或y)生成组。您能更清楚一点,哪一列是您的id列吗?您确定您的dt.所需的正确吗?如果在dt[,id:=.I]
上放置索引列,则表明第一组是第1行和第122行?为什么输出的第一个值为0?是不是应该是10?那是相当整洁的。尽管cpp的速度惊人地快(31人而不是30人),但您的团队只差一个元素。很好。@StefanF-你确定我只差一个元素吗?@NealBarsch-是的。值得记住的是,“矢量化”几乎是用编译语言编写的循环,通常是C
,C++
或fortran
尝试表(dt[,.N[[1]],by=“grp”]$V1)
,至少在我的机器上,它给我的大小是错误的(第一组是30个元素,后面一组是31个)。在编辑我的原始解决方案之前,我遇到了与之相反的问题(例如,我的第一组解决方案太小了)。这dt[dt[,.I[c(1,N)],by=grp2]$V1]
非常简洁。尽管cpp的速度惊人地快(31人而不是30人),但您的团队只差一个元素。很好。@StefanF-你确定我只差一个元素吗?@NealBarsch-是的。值得记住的是,“矢量化”几乎是用编译语言编写的循环,通常是C
,C++
或fortran
尝试表(dt[,.N[[1]],by=“grp”]$V1)
,至少在我的机器上,它给我的大小是错误的(第一组是30个元素,后面一组是31个)。在编辑原始解决方案之前,我遇到了与之相反的问题(例如,我的第一个组太小)。