【问题标题】:Filter conditionally in a pipe in R在R中的管道中有条件地过滤
【发布时间】:2021-03-25 23:23:19
【问题描述】:

我有很多数据框,每个都有几列。其中两列是timevalue

小例子

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 &gt; 10

当数据框包含values &gt; 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 管道中解决这个问题?是否可以进行条件过滤?

【问题讨论】:

    标签: r dataframe filter dplyr pipe


    【解决方案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()))
    

    微基准测试

    在速度方面,filterslice 差别不大:

    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
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-07-29
      • 1970-01-01
      • 2021-12-11
      • 1970-01-01
      • 2021-06-05
      • 1970-01-01
      • 2019-12-08
      • 2019-07-27
      相关资源
      最近更新 更多