在 R 的管道中有条件地过滤
Filter conditionally in a pipe in R
我有很多数据框,每个都有几列。其中两列是 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
解决方案时,它 returns 一个空数据框。
问题
如何在 dplyr
管道内解决这个问题?是否可以进行条件过滤?
您可以在 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
我有很多数据框,每个都有几列。其中两列是 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
解决方案时,它 returns 一个空数据框。
问题
如何在 dplyr
管道内解决这个问题?是否可以进行条件过滤?
您可以在 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