Фильтрация строк между нулевыми значениями и сохранение в качестве новых фреймов данных или таблиц данных в R

#r #dataframe #filter #group-by #datatables

#r #фрейм данных #Фильтр #группирование по #таблицы данных

Вопрос:

У меня есть большой набор данных csv с более чем 45 тыс. строк и 19 различными переменными. Я хотел бы отфильтровать его по определенной переменной (V4), чтобы каждая отфильтрованная группа начиналась с 0, а затем следующий 0 будет означать начало новой group / dataframe / datatable, сохраняя при этом все остальные переменные внутри этой новой таблицы. Мне нужны эти отдельные группы для дальнейшего анализа каждого случая данных. Я пытался:

 filtered_data <- my_data %>%       
group_by("V4") %>%       
filter("V4" == 0 amp; "V4" !=0)      
View(filtered_data)    
  

Кажется, что первый «V4» == 0 работает, но я пытаюсь определить конец каждого отфильтрованного фрейма данных, например, как фильтровать от 0 до 3, затем от 0 до 5 и т.д.
Как я могу определить длину каждого случая? Существует ли логический оператор, который сохраняет каждую группу до того, как V4 снова превратится в 0? Или было бы лучше создать цикл?

Пример my_data:

         V1    V2    V3    V4    .    .    .    V19 
    1                     0
    2                     1
    3                     2
    4        `            3
    5                     0
    6                     1
    7                     2
    8                     3
    9                     4
    10                    5
    11                    0
   ...
   45k   
  

Ответ №1:

Вот способ сгруппировать ваши строки с помощью базовой арифметики. Я создаю группы, используя совокупную сумму индикаторной переменной (V4 равно 0 или нет), и разбиваю data.frame на отдельные фреймы данных, используя group_split .

 # example data 12000 rows in total, 4000 groups of 3 rows
df <- data.frame(V1 = 1:12000, 
                 V2 = sample(LETTERS, 12000, replace = T), 
                 V4 = rep(0:2, 4000))

df <- df %>%
  mutate(Groups = ifelse(V4 == 0, 1, 0),
         Groups = cumsum(Groups)) %>%
  group_split(Groups)
  

Итак, первая группа / фрейм данных

 > df[[1]]
# A tibble: 3 x 4
     V1 V2       V4 Groups
  <int> <chr> <int>  <dbl>
1     1 L         0      1
2     2 L         1      1
3     3 Y         2      1
  

второй

 > df[[2]]
# A tibble: 3 x 4
     V1 V2       V4 Groups
  <int> <chr> <int>  <dbl>
1     4 Z         0      2
2     5 N         1      2
3     6 Y         2      2
  

и так далее.

Если вы хотите сохранить каждый data.frame отдельно, вы могли бы использовать что-то вроде этого:

 # new environment that holds all data.frames
dfEnv <- new.env()

df %>%
  mutate(Groups = ifelse(V4 == 0, 1, 0),
         Groups = cumsum(Groups)) %>%
  group_by(Groups) %>%
  do({
    # save every group inside the new environment as a single data.frame
    dfEnv[[paste0("Group_", unique(.$Groups))]] <- .
  })
  

Теперь у вас есть dfEnv$Group_1 , dfEnv$Group_2 , … и так далее.
Внутри do() вы также можете использовать saveRDS или write.csv для сохранения данных на диск.

Комментарии:

1. Спасибо! Я замечаю, что для вычисления требуется много времени, например, более 1600 групп, поскольку каждая из них печатается на экране и не сохраняется отдельно. Есть ли какой-либо способ ускорить этот процесс?

2. Просто сохраните список, тогда ничего не будет напечатано. Я редактирую свой ответ.