从具有选择条件的一个中提取多个 data.frames

Extract multiple data.frames from one with selection criteria

假设这是我的数据集:

df <- data.frame(x1 = runif(1000), x2 = runif(1000), x3 = runif(1000), 
             split = sample( c('SPLITMEHERE', 'OBS'), 1000, replace=TRUE, prob=c(0.04, 0.96) ))

所以,我有一些变量(在我的例子中是 15),以及我想将 data.frame 分成多个 data.frame 的标准。

我的标准如下:每次出现 'SPLITMEHERE' 我想获取所有值,或低于它的所有 'OBS' 并从这些观察中得到 data.frame .所以,如果开始 data.frame 有 20 'SPLITMEHERE's,我希望最后有 10 data.frames。

我知道这听起来令人困惑并且没有多大意义,但这是从非常脏的 .txt 文件中提取原始数字以获得有意义的数据的结果。基本上每个'SPLITMEHERE'表示这个.txt文件中的新table,但是每个县分为两个table,所以我想要一个table(data.frame) 每个县。

希望我能说得更清楚,这里是我需要的例子。假设前 20 个观察结果是:

             x1          x2           x3       split
1    0.307379064 0.400526799 0.2898194543         SPLITMEHERE
2    0.465236674 0.915204924 0.5168274657         OBS
3    0.063814420 0.110380201 0.9564822116         OBS
4    0.401881416 0.581895095 0.9443995396         OBS
5    0.495227871 0.054014926 0.9059893533         SPLITMEHERE
6    0.091463620 0.945452614 0.9677482590         OBS
7    0.876123151 0.702328031 0.9739113525         OBS
8    0.413120761 0.441159673 0.4725571219         OBS
9    0.117764512 0.390644966 0.3511555807         OBS
10   0.576699384 0.416279417 0.8961428872         OBS
11   0.854786077 0.164332814 0.1609375612         OBS
12   0.336853841 0.794020157 0.0647337821         SPLITMEHERE
13   0.122690541 0.700047133 0.9701538396         OBS
14   0.733926139 0.785366852 0.8938749305         OBS
15   0.520766503 0.616765349 0.5136788010         OBS
16   0.628549288 0.027319848 0.4509875809         OBS
17   0.944188977 0.913900539 0.3767973795         OBS
18   0.723421337 0.446724318 0.0925365961         OBS
19   0.758001243 0.530991725 0.3916394396         SPLITMEHERE
20   0.888036748 0.862066601 0.6501050976         OBS

我想得到的是:

data.frame1:

1    0.465236674 0.915204924 0.5168274657         OBS
2    0.063814420 0.110380201 0.9564822116         OBS
3    0.401881416 0.581895095 0.9443995396         OBS
4    0.091463620 0.945452614 0.9677482590         OBS
5    0.876123151 0.702328031 0.9739113525         OBS
6    0.413120761 0.441159673 0.4725571219         OBS
7    0.117764512 0.390644966 0.3511555807         OBS
8    0.576699384 0.416279417 0.8961428872         OBS
9    0.854786077 0.164332814 0.1609375612         OBS

data.frame2:
    1   0.122690541 0.700047133 0.9701538396         OBS
    2   0.733926139 0.785366852 0.8938749305         OBS
    3   0.520766503 0.616765349 0.5136788010         OBS
    4   0.628549288 0.027319848 0.4509875809         OBS
    5   0.944188977 0.913900539 0.3767973795         OBS
    6   0.723421337 0.446724318 0.0925365961         OBS
    7   0.888036748 0.862066601 0.6501050976         OBS

因此,拆分列只是告诉我拆分的位置,写入'SPLITMEHERE'的列中的数据是没有意义的。但是,这并不麻烦,因为我可以稍后删除这些行,重点是根据这个标准分隔多个 data.frames。

显然,split() 函数和 dplyr 中的 filter() 在这里是不够的。真正的问题是应该分隔 data.frame 的行(即每隔一个 'SPLITMEHERE')不会以常规方式出现,但就像我上面的例子一样。一旦有 3 行的间隙,其他时候可能是 10 或 15 行。

有什么方法可以在 R 中有效地提取它吗?

问题中最难的部分是创建组。一旦我们进行了适当的分组,就可以很容易地使用 split 来获得结果。

话虽如此,您可以对群组使用 cumsum。在这里,我将 cumsum 除以 2 并使用 ceiling,这样任何 2 SPLITMEHERE 的组都将折叠成一个。我还使用 ifelse 来排除 SPLITMEHERE:

的行
df$group <- ifelse(df$split != "SPLITMEHERE", ceiling(cumsum(df$split=="SPLITMEHERE")/2), 0)
res <- split(df, df$group)

结果是一个列表,其中每个 group 都有一个数据框。带有 0 的组是您要删除的组。