Извлечение нескольких фреймов данных из одного с критериями выбора

Пусть это будет мой набор данных:

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.frames.

Мои критерии следующие: каждый раз, когда появляется "SPLITMEHERE", я хочу взять все значения или все "OBS" под ним и получить data.frame только из этих наблюдений. Итак, если в начале data.frame 20 'SPLITMEHERE', я хочу в итоге получить 10 data.frames.

Я знаю, что это звучит запутанно и похоже, что в этом нет особого смысла, но это результат извлечения необработанных чисел из ужасно грязного файла.txt для получения значимых данных. По сути, каждый 'SPLITMEHERE' обозначает новую таблицу в этом файле.txt, но каждый округ делится на две таблицы, поэтому я хочу одну таблицу (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" бессмысленно. Но это не беспокоит, так как я могу удалить эти строки позже, дело в том, чтобы разделить несколько фреймов данных на основе этого критерия.

Очевидно, что только split() функция и filter() от dplyr здесь бы не хватило Реальная проблема заключается в том, что строки, которые должны разделять data.frames (то есть все остальные 'SPLITMEHERE'), появляются не так, как в моем предыдущем примере. Когда-то есть разрыв в 3 строки, а в других случаях это может быть 10 или 15 строк.

Есть ли способ извлечь это эффективно в R?

1 ответ

Решение

Самая трудная часть проблемы - это создание групп. Как только у нас будут правильные группировки, достаточно просто использовать 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 те, которые вы хотите выбросить.

Другие вопросы по тегам