我的虚拟输入向量如下所示:
x <- c(10, 20, 30, 70, 80, 90, 130, 190, 200)
我想要什么:为每个号码添加组因子。根据相邻号码之间的差异分配组。
示例:
10到20之间的差异(绝对)是10,因此它们属于同一组
30到20之间的差异是10 - 它们属于同一组
30到70之间的差异是40 - 它们属于不同的群体。
鉴于最大差异20
想要的结果是:
x group
10 1
20 1
30 1
70 4
80 4
90 4
130 7
190 8
200 8
我的代码:
library(data.table)
library(foreach)
x <- c(10, 20, 30, 70, 80, 90, 130, 190, 200)
x <- data.table(x, group = 1)
y <- nrow(x)
maxGap <- 20
g <- 1
groups <-
foreach(i = 2:y, .combine = rbind) %do% {
if (x[i, x] - x[i - 1, x] < maxGap) {
g
} else {
g <- i
g
}
}
x[2:y]$group <- as.vector(groups)
我的问题
鉴于代码有效,但是对于大数据(行数> 10mil)来说太慢了。是否有更简单,更快速的解决方案(不使用循环)?
答案 0 :(得分:4)
string[] lines = File.ReadAllLines(@"StudentExamMarks.txt");
string maxForeName = null;
string maxSurName = null;
var maxMark = 0;
for (int i = 0; i < lines.Length; i++)
{
var tmp = lines[i].Split(new char[] { ' ', '.', ':' }, StringSplitOptions.RemoveEmptyEntries);
if (tmp.Length == 3)
{
int value = int.Parse(tmp[2]);
if (i == 0 || value > maxMark)
{
maxMark = value;
maxForeName = tmp[0];
maxSurName = tmp[1];
}
}
}
答案 1 :(得分:3)
使用 data.table 的rleid
和shift
函数的实现:
x <- c(10, 20, 30, 70, 80, 90, 130, 190, 200)
DT <- data.table(x)
DT[, grp := rleid(cumsum(x - shift(x,1L,0) > 20))]
给出:
> DT
x grp
1: 10 1
2: 20 1
3: 30 1
4: 70 2
5: 80 2
6: 90 2
7: 130 3
8: 190 4
9: 200 4
解释:使用x - shift(x,1L,0)
计算与先前x
观察值的差异。通过将其与20
(即> 20
部分)进行比较,并将其包含在cumsum
和rleid
中,可以创建游程长度。
回应@Roland的评论:如果您将rleid
中的fill
参数设置为shift
,则可以退出-Inf
- 部分:< / p>
DT[, grp := cumsum((x - shift(x, 1L, -Inf)) > 20)]
答案 2 :(得分:2)
test <- c(TRUE, diff(x) > 20) #test the differences
res <- factor(cumsum(test)) #groups
#[1] 1 1 1 2 2 2 3 4 4
#Levels: 1 2 3 4
levels(res) <- which(test) #fix levels
res
#[1] 1 1 1 4 4 4 7 8 8
#Levels: 1 4 7 8