#r #dplyr #tidyverse
Вопрос:
Я хочу найти список предыдущих максимумов. Итак, для вектора: 3, 2,2,3,4,3,9,5,2,3,4,6,120,1 Первый максимум равен 3, второй максимум равен 4 (потому что, 4gt;3), затем 9(потому что 9gt;gt;4) , а затем 120 (120gt;gt;gt;9) Итак, в качестве вывода мне понадобится позиция: 1,5,7,13
Есть ли в любом случае способ сделать это без цикла for?
``` vectorlt;-c(3, 2,2,3,4,3,9,5,2,3,4,6,120,1) resultslt;-1 maxlt;-3 for(i in 2:length(vector)){ if(vector[i]gt;max{ resultslt;-c(results, i) maxlt;-vector[i]} else {next} } ```
Комментарии:
1. Зачем вам это нужно делать
dplyr
?2.
match(unique(x lt;- cummax(vector)), x)
3.
with(rle(cummax(x)), which(sequence(lengths)==1))
еще один странный способ
Ответ №1:
Это можно сделать с помощью кодирования длины выполнения:
vec lt;- c(3,2,2,3,4,3,9,5,2,3,4,6,120,1) r lt;- rle(cummax(vec)) c(1, 1 cumsum(r$lengths)[-length(r$lengths)]) # [1] 1 5 7 13
И вариант от @user20650, который короче и лаконичнее (спасибо!):
which(as.logical(c(1, diff(cummax(vec))))) # [1] 1 5 7 13
Комментарии:
1. Действительно, гораздо короче, приятно.
Ответ №2:
Может быть, другое решение с dplyr
и tibble
:
library(dplyr) library(tibble) cummax(vector) %gt;% enframe() %gt;% group_by(value) %gt;% slice_head() %gt;% pull(name) [1] 1 5 7 13
Ответ №3:
Другой способ-использовать рекурсивную функцию
findAllMaximums lt;- function(data, index = 1, results = c()){ if(index == length(data)) return(results) if(index==1) return(findAllMaximums(data, index 1, index)) if(data[index] gt; max(data[results])) results = append(results, index) return(findAllMaximums(data, index 1, results)) } vectorlt;-c(3, 2,2,3,4,3,9,5,2,3,4,6,120,1) print(findAllMaximums(vector))
Ответ №4:
sapply(split(1:length(vector), cummax(vector)), `[`, 1) ## 3 4 9 120 lt;- the names of the result vector (=max values) ## 1 5 7 13 lt;- the values (=indexes)
Возьмите только первых членов cummax()
группы.