Фильтр условно в канале в R

#r #dataframe #filter #dplyr #pipe

#r #dataframe #Фильтр #dplyr #канал

Вопрос:

У меня много фреймов данных, каждый из которых содержит несколько столбцов. Двумя из этих столбцов являются time и value .

Минимальный пример

 library(tidyverse)

df <- approx(seq(1,10,1), c(1,5,7,11,4,12,30, 20, 10, 9)) %>% 
      as.data.frame() %>% 
      rename(time = x, value = y)
 

Цель

Я хочу удалить все строки из каждого фрейма данных, начиная с первого раза value > 10 .

Когда фрейм данных содержит values > 10 , решение будет следующим:

 df <- df %>% 
         filter(row_number() <= first(which(value > 10))-1)
 

Однако существуют также фреймы данных, где значение value не превышает 10 , например,

 df <- approx(seq(1,10,1), c(1,5,7,1,4,2,1, 2, 1, 9)) %>% 
      as.data.frame() %>% 
      rename(time = x, value = y)
 

В этом случае фрейм данных не должен фильтроваться (поскольку value пороговое значение не достигнуто). Однако, когда я использую filter решение выше, оно возвращает пустой фрейм данных.

Вопрос

Как бы вы решили эту проблему внутри dplyr канала? Возможно ли выполнить условную фильтрацию?

Ответ №1:

Вы могли бы написать условный оператор в filter :

 library(dplyr)

df %>% 
    filter(if(any(value > 10)) row_number() <= which.max(value > 10)-1 else TRUE)
 

Запись той же логики в slice :

 df %>% 
   slice(if(any(value > 10)) seq_len(which.max(value > 10)-1) else seq_len(n()))
 

Микробеншмарк

С точки зрения скорости, нет большой разницы между filter и slice :

 df <- approx(seq(1,10^5,1), 
             round( runif(10^5, min = 1, max = 10^10) ) ) %>% 
      as.data.frame()

library(microbenchmark)

microbenchmark(
  filter = df %>% filter(if(any(value > 10)) row_number() <= which.max(value > 10)-1 else TRUE),
  slice = df %>% slice(if(any(value > 10)) seq_len(which.max(value > 10)-1) else seq_len(n())), times = 10000)

Unit: microseconds
  expr     min       lq     mean   median       uq      max neval
 filter 551.522 570.2715 655.7250 586.3530 621.5590 13575.81 10000
 slice 614.276 633.6840 735.0398 654.2455 695.3795 14123.43 10000