минимум или максимум с помощью фильтра

#r #dplyr

Вопрос:

Фрейм данных:

 mydf <- data.frame(
  date = seq(as.Date('2021-01-01'), as.Date('2021-01-20'), by = 'days'),
  blah = rnorm(20, 0),
  y = LETTERS[1:20]
)
 

Я хочу отфильтровать дату так, чтобы она доходила до максимального значения бла, превышающего 0.

Пытался:

 mydf %>% filter(date <= (. %>% filter(blah > 0) %>% pull(date) %>% max))
 

Что дало ошибку:

 Error: Problem with `filter()` input `..1`.
x comparison (4) is possible only for atomic and list types
ℹ Input `..1` is `date <= (. %>% filter(blah >= 0) %>% pull(date) %>% max)`.
 

Как я могу фильтровать таким образом?

Ответ №1:

Вместо того, чтобы выводить, проще подмножество «дата», где » бла » больше 0, и создать логическое с date

 library(dplyr)
mydf %>%
     filter(date <= max(date[blah >0]))
 

Ответ №2:

Используя эти случайные данные:

 set.seed(42)
mydf <- data.frame(
  date = seq(as.Date('2021-01-01'), as.Date('2021-01-20'), by = 'days'),
  blah = rnorm(20, 0),
  y = LETTERS[1:20]
)
mydf
#          date        blah y
# 1  2021-01-01  1.37095845 A
# 2  2021-01-02 -0.56469817 B
# 3  2021-01-03  0.36312841 C
# 4  2021-01-04  0.63286260 D
# 5  2021-01-05  0.40426832 E
# 6  2021-01-06 -0.10612452 F
# 7  2021-01-07  1.51152200 G
# 8  2021-01-08 -0.09465904 H
# 9  2021-01-09  2.01842371 I
# 10 2021-01-10 -0.06271410 J
# 11 2021-01-11  1.30486965 K
# 12 2021-01-12  2.28664539 L
# 13 2021-01-13 -1.38886070 M
# 14 2021-01-14 -0.27878877 N
# 15 2021-01-15 -0.13332134 O
# 16 2021-01-16  0.63595040 P
# 17 2021-01-17 -0.28425292 Q
# 18 2021-01-18 -2.65645542 R
# 19 2021-01-19 -2.44046693 S
# 20 2021-01-20  1.32011335 T
 

Можно сделать:

 mydf %>%
  filter(row_number() <= which.max(blah)) %>%
  pull(date)
#  [1] "2021-01-01" "2021-01-02" "2021-01-03" "2021-01-04" "2021-01-05" "2021-01-06" "2021-01-07" "2021-01-08" "2021-01-09"
# [10] "2021-01-10" "2021-01-11" "2021-01-12"
mydf %>%
  filter(row_number() <= which.max(blah))
#          date        blah y
# 1  2021-01-01  1.37095845 A
# 2  2021-01-02 -0.56469817 B
# 3  2021-01-03  0.36312841 C
# 4  2021-01-04  0.63286260 D
# 5  2021-01-05  0.40426832 E
# 6  2021-01-06 -0.10612452 F
# 7  2021-01-07  1.51152200 G
# 8  2021-01-08 -0.09465904 H
# 9  2021-01-09  2.01842371 I
# 10 2021-01-10 -0.06271410 J
# 11 2021-01-11  1.30486965 K
# 12 2021-01-12  2.28664539 L
 

Это предполагает, что date это не уменьшается; если это не гарантия, то можно сделать:

 mydf %>%
  filter(date <= date[which.max(blah)])
#          date        blah y
# 1  2021-01-01  1.37095845 A
# 2  2021-01-02 -0.56469817 B
# 3  2021-01-03  0.36312841 C
# 4  2021-01-04  0.63286260 D
# 5  2021-01-05  0.40426832 E
# 6  2021-01-06 -0.10612452 F
# 7  2021-01-07  1.51152200 G
# 8  2021-01-08 -0.09465904 H
# 9  2021-01-09  2.01842371 I
# 10 2021-01-10 -0.06271410 J
# 11 2021-01-11  1.30486965 K
# 12 2021-01-12  2.28664539 L
 

Ответ №3:

Я заставил его работать, заключив фигурные скобки вокруг точки:

 mydf %>% filter(date <= ({.} %>% filter(blah > 0) %>% pull(date) %>% max))
 

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

1. Это меня смущает. «максимальное значение бла, превышающее 0» , предполагает что-то вроде which.max(blah[blah>0]) (что, учитывая вероятное наличие положительных чисел, вероятно, совпадает с which.max(blah) ). Однако вы используете его только max на самом date поле.

2. Да, я мог бы получше сформулировать это! «Min by» или «max by» или «групповой минимум или максимум» могут быть лучшими выражениями? Примените условие к одному полю (бла-бла), а затем получите минимальное или максимальное значение в другом поле (дата).