Отфильтруйте все строки df ниже определенного значения определенного столбца

#r #lubridate #dplyr

Вопрос:

У меня есть df, в котором есть две колонки, time и val . df упорядочен по времени. Я хочу отфильтровать все строки от максимального значения, в данном случае это так 1.29 . Я привел пример ниже:

 library(tidyverse)
library(lubridate)


# This is the entire df
df1 <- tibble::tribble(
  ~date, ~val,
  "2021-09-16 11:02:45", 1.21,
  "2021-09-16 11:02:45", 1.21,
  "2021-09-16 11:02:45", 1.21,
  "2021-09-16 11:02:45", 1.22,
  "2021-09-16 11:02:45", 1.22,
  "2021-09-16 11:02:45", 1.22,
  "2021-09-16 11:02:37", 1.22,
  "2021-09-16 10:59:29", 1.29,
  "2021-09-16 10:59:14", 1.29,
  "2021-09-16 10:59:14", 1.28,
  "2021-09-16 10:59:14", 1.28,
  "2021-09-16 10:58:17", 1.28,
  "2021-09-16 10:58:17", 1.28,
  "2021-09-16 10:58:05", 1.26,
  "2021-09-16 10:58:05", 1.26,
  "2021-09-16 10:58:05", 1.23,
  "2021-09-16 10:57:16", 1.23
  
  ) %>%
  mutate(date = ymd_hms(date))


# This is the outcome I am looking for
tibble::tribble(
  ~date, ~val,
  "2021-09-16 10:59:29", 1.29,
  "2021-09-16 10:59:14", 1.29,
  "2021-09-16 10:59:14", 1.28,
  "2021-09-16 10:59:14", 1.28,
  "2021-09-16 10:58:17", 1.28,
  "2021-09-16 10:58:17", 1.28,
  "2021-09-16 10:58:05", 1.26,
  "2021-09-16 10:58:05", 1.26,
  "2021-09-16 10:58:05", 1.23,
  "2021-09-16 10:57:16", 1.23
  
) %>%
  mutate(date = ymd_hms(date))
 

Как это сделать эффективно, есть какие-нибудь идеи?

Ответ №1:

Если я правильно понял, это может решить вашу проблему

 library(dplyr)

df1 %>% 
  filter(date <= first(date[val == max(val)]))

# A tibble: 10 x 2
   date                  val
   <dttm>              <dbl>
 1 2021-09-16 10:59:29  1.29
 2 2021-09-16 10:59:14  1.29
 3 2021-09-16 10:59:14  1.28
 4 2021-09-16 10:59:14  1.28
 5 2021-09-16 10:58:17  1.28
 6 2021-09-16 10:58:17  1.28
 7 2021-09-16 10:58:05  1.26
 8 2021-09-16 10:58:05  1.26
 9 2021-09-16 10:58:05  1.23
10 2021-09-16 10:57:16  1.23
 

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

1. вот и все! Из какой библиотеки вы first пришли?

2. @головоногий моллюск dplyr

Ответ №2:

Вот несколько других dplyr вариантов использования match .

  1. С помощью slice
 library(dplyr)
df1 %>% slice(match(max(val), val):n())

#   date                  val
#   <dttm>              <dbl>
# 1 2021-09-16 10:59:29  1.29
# 2 2021-09-16 10:59:14  1.29
# 3 2021-09-16 10:59:14  1.28
# 4 2021-09-16 10:59:14  1.28
# 5 2021-09-16 10:58:17  1.28
# 6 2021-09-16 10:58:17  1.28
# 7 2021-09-16 10:58:05  1.26
# 8 2021-09-16 10:58:05  1.26
# 9 2021-09-16 10:58:05  1.23
#10 2021-09-16 10:57:16  1.23
 
  1. С помощью filter
 df1 %>% filter(row_number() >= match(max(val), val))
 

Вы также можете использовать базу R, чтобы сделать то же самое.

 df1[match(max(df1$val), df1$val):nrow(df1), ]         
 

Ответ №3:

Мы можем использовать

 library(dplyr)
df1 %>% 
    filter(row_number() >=which.max(val))
 

-выход

 # A tibble: 10 x 2
   date                  val
   <dttm>              <dbl>
 1 2021-09-16 10:59:29  1.29
 2 2021-09-16 10:59:14  1.29
 3 2021-09-16 10:59:14  1.28
 4 2021-09-16 10:59:14  1.28
 5 2021-09-16 10:58:17  1.28
 6 2021-09-16 10:58:17  1.28
 7 2021-09-16 10:58:05  1.26
 8 2021-09-16 10:58:05  1.26
 9 2021-09-16 10:58:05  1.23
10 2021-09-16 10:57:16  1.23
 

Ответ №4:

 df1 %>%
  filter(cumsum(val == max(val)) >= 1)
 

Здесь мы сохраняем строки, для которых совокупное время, в течение которого мы достигли максимального значения, составляет по крайней мере одну.

Я предполагаю, что здесь данные уже отсортированы по дате.