从大型数据集中制作重复数据的子集

时间:2019-04-15 17:27:05

标签: r subset

我正在尝试使用R从大型数据集中提取某些数据。该数据来自一个过程,该过程经历了多个阶段,比如说阶段0到5。我有一个数据集,其中包含该过程的多次运行。

我正在尝试为每个运行提取数据。我想创建一个子集,该子集的第一个出现的阶段为0到5,然后创建另一个子集,其状态为另一个阶段0到5(第二轮)。数据集仅包含按时间顺序排列的过程数据和阶段号,它不告诉它在哪个运行中。但是,阶段是按顺序进行的,因此阶段列从0到5,然后再次从0开始。

我已经尝试过使用while和for循环来组织数据,但是在这么大的数据集(700 000个条目)上,这非常慢。即使只使用10000个条目的一小部分,也要花费很长时间。

数据集可能看起来像这样(第二列是阶段):

01, 0, 2, 4, 5, 3, 4,
02, 0, 3, 4, 5, 2, 2,
03, 0, 4, 5, 4, 9, 8,
04, 1, 8, 9, 2, 7, 3,
05, 1, 8, 7, 0, 7, 8,
06, 2, 8, 4, 9, 7, 8,
07, 2, 9, 7, 5, 0, 8,
08, 2, 8, 6, 5, 7, 9,
07, 2, 8, 7, 6, 7, 9,
08, 3, 7, 8, 6, 7, 9,
09, 3, 7, 9, 8, 7, 8, 
10, 4, 5, 6, 7, 4, 3,
11, 4, 6, 7, 5, 6, 4,
12, 5, 6, 4, 3, 2, 2,
13, 0, 6, 3, 3, 2, 5,
14, 0, 5, 6, 3, 2, 2,
15, 1, 5, 2, 1, 4, 4,

请注意,每相的行数不是恒定的。

我从上面的示例中期望的子集将是:

01, 0, 2, 4, 5, 3, 4,
02, 0, 3, 4, 5, 2, 2,
03, 0, 4, 5, 4, 9, 8,
04, 1, 8, 9, 2, 7, 3,
05, 1, 8, 7, 0, 7, 8,
06, 2, 8, 4, 9, 7, 8,
07, 2, 9, 7, 5, 0, 8,
08, 2, 8, 6, 5, 7, 9,
07, 2, 8, 7, 6, 7, 9,
08, 3, 7, 8, 6, 7, 9,
09, 3, 7, 9, 8, 7, 8, 
10, 4, 5, 6, 7, 4, 3,
11, 4, 6, 7, 5, 6, 4,
12, 5, 6, 4, 3, 2, 2,

13, 0, 6, 3, 3, 2, 5,
14, 0, 5, 6, 3, 2, 2,
15, 1, 5, 2, 1, 4, 4,

(注意:在原始数据集中,相位将始终以5结尾)

2 个答案:

答案 0 :(得分:2)

在您的问题中,只有在相位索引(在第二列中给出)减小的情况下,才会启动一个新的子集。因此,我们可以将whichdiff结合起来,以获得一个阶段结束的行索引。

我们首先可以获取子集开始/结束的行索引,如下所示:

end   <- which(diff(data[,2]) < 0)
start <- c(1, end + 1)
end   <- c(end, nrow(data))

然后我们可以使用它来创建包含子集的列表,如下所示:

subsets <- vector("list", length(start))

for (idx in 1:length(start))
  subsets[[idx]] <- data[start[idx]:end[idx],]

请注意,最后一步仍然使用for循环。我希望split可以达到类似的效果,但是我没有成功尝试。

编辑:当然,R有一个避免使用for语句的解决方案。我们应该创建一个新的向量,为每一行指示其所属的子集。给定以上两个向量endstart,可以轻松实现(请参见下面的代码段)。然后,我们可以使用内置函数split并将其输出转换为矩阵列表(受this answer启发)。

# How many rows does each subset has?
n <- end - start + 1

# Create vector that indicates for each row to which subset it belongs 
idx_subset <- rep(1:length(start), n)

# Create the subsets
subsets <- lapply( split(data, idx_subset), matrix, ncol=7)

答案 1 :(得分:1)

这是向量化的解决方案

# sample df
df = read.table(text = "
v1  phase   v3  v4  v5  v6  v7
01  0   2   4   5   3   4
02  0   3   4   5   2   2
03  0   4   5   4   9   8
04  1   8   9   2   7   3
05  1   8   7   0   7   8
06  2   8   4   9   7   8
07  2   9   7   5   0   8
08  2   8   6   5   7   9
07  2   8   7   6   7   9
08  3   7   8   6   7   9
09  3   7   9   8   7   8   
10  4   5   6   7   4   3
11  4   6   7   5   6   4
12  5   6   4   3   2   2
13  0   6   3   3   2   5
14  0   5   6   3   2   2
15  1   5   2   1   4   4
                ", stringsAsFactors = F, header = T)

# create groups for splitting df
grp <- cumsum( c( 0, diff( df$phase ) ) < 0 ) + 1

# split the df
split(df, grp)
#> $`1`
#>    v1 phase v3 v4 v5 v6 v7
#> 1   1     0  2  4  5  3  4
#> 2   2     0  3  4  5  2  2
#> 3   3     0  4  5  4  9  8
#> 4   4     1  8  9  2  7  3
#> 5   5     1  8  7  0  7  8
#> 6   6     2  8  4  9  7  8
#> 7   7     2  9  7  5  0  8
#> 8   8     2  8  6  5  7  9
#> 9   7     2  8  7  6  7  9
#> 10  8     3  7  8  6  7  9
#> 11  9     3  7  9  8  7  8
#> 12 10     4  5  6  7  4  3
#> 13 11     4  6  7  5  6  4
#> 14 12     5  6  4  3  2  2
#> 
#> $`2`
#>    v1 phase v3 v4 v5 v6 v7
#> 15 13     0  6  3  3  2  5
#> 16 14     0  5  6  3  2  2
#> 17 15     1  5  2  1  4  4

reprex package(v0.2.1)于2019-04-15创建

说明:diff计算特定值与其前一个值的差,然后<运算符评估结果是否小于0。所得的逻辑向量T, F在前面附加另一个0,以保持向量长度与df中的行数相同。 cumsum然后找到值的累积运行总和,该值仅在阶段5之后紧随一个较小的阶段值时才会更改,因此实际上创建了组。然后使用这些组(grp来拆分df