Как остановить функцию slide() от вычисления числового вектора в список?

#r #dplyr

#r #dplyr

Вопрос:

У меня есть data.frame один столбец:

 Price <- c(1, 2, 5, 3, 1, 4, 7, 10, 6)
df <- data.frame(Price)
 

Я хочу вычислить максимальное значение каждого из семи чисел, в результате чего:

 df$MaxPrice <- c(1, 2, 5, 5, 5, 5, 7, 10, 10)
 

Однако, когда я пытаюсь вычислить этот новый столбец с mutate() помощью and slide() , он возвращает мне список внутри фрейма данных вместо числовой переменной:

 library(dplyr)
library(slider)

df <- df %>% 
  mutate(MaxPrice = slide(Price, max, .before = 7, .after = 0, .complete = F))
 

Почему это происходит и как заставить slide() возвращать числовую переменную?

Ответ №1:

Похоже, что метод по умолчанию вызывает list вывод. Согласно ?slide

vec_ptype(slide(.x)) == list()

и описание для .ptype этого

.ptype — [вектор(0) / NULL]

Прототип, соответствующий типу выходного сигнала.

Если значение по умолчанию равно NULL, то тип вывода определяется путем вычисления общего типа для результатов вызовов .f.

Если указано, результат каждого вызова .f будет приведен к этому типу, и конечный результат будет иметь этот тип.

Если getOption(«vctrs.no_guessing») имеет значение TRUE, должен быть указан .ptype . Это способ заставить производственный код требовать фиксированных типов.

По сути, основываясь на исходном коде (ниже), он по умолчанию возвращает a list , и, похоже, нет возможности предотвратить это, если мы не выберем конкретные описанные методы, т.е. _vec или _dbl

Либо мы могли бы flatten

 library(dplyr)
library(slider)
library(purrr)
out <- df %>% 
    mutate(MaxPrice = slide(Price, max, .before = 7, .after = 0,
       .complete = FALSE) %>% flatten_dbl) 

str(out)
#'data.frame':  9 obs. of  2 variables:
# $ Price   : num  1 2 5 3 1 4 7 10 6
# $ MaxPrice: num  1 2 5 5 5 5 7 10 10
 

Или используйте метод, зависящий от типа, т.е. slide_dbl

 out <- df %>% 
    mutate(MaxPrice = slide_dbl(Price, max, .before = 7, .after = 0,
       .complete = FALSE) )

str(out)
#'data.frame':  9 obs. of  2 variables:
# $ Price   : num  1 2 5 3 1 4 7 10 6
# $ MaxPrice: num  1 2 5 5 5 5 7 10 10
 

Если мы проверяем исходный код slide , он вызывает slide_impl и предполагает, что .ptype as list и нет возможности передать эту информацию slide

 slide
function (.x, .f, ..., .before = 0L, .after = 0L, .step = 1L, 
    .complete = FALSE) 
{
    slide_impl(.x, .f, ..., .before = .before, .after = .after, 
        .step = .step, .complete = .complete, .ptype = list(), 
        .constrain = FALSE, .atomic = FALSE)
}
 

Теперь сравните это с _dbl методом

 slide_dbl
function (.x, .f, ..., .before = 0L, .after = 0L, .step = 1L, 
    .complete = FALSE) 
{
    slide_vec_direct(.x, .f, ..., .before = .before, .after = .after, 
        .step = .step, .complete = .complete, .ptype = double())
}
 

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

1. Спасибо, это сработало. Однако я могу принять его только через 10 минут. Вы знаете, почему это произошло именно так? Я имею в виду, slide() не всегда возвращает списки, не так ли?

2. @Escurisse Это связано с исходным кодом. Я обновил сообщение.

3. Спасибо за ваш подробный ответ!

Ответ №2:

Вы можете просто использовать cummax функцию в базе R:

 Price <- c(1, 2, 5, 3, 1, 4, 7, 10, 6)
cummax(Price)
[1]  1  2  5  5  5  5  7 10 10
 

Для многовекторного случая. Загрузите вектор данных в матрицу и примените cummax к столбцам. Генерирует матрицу векторов cummax для последующей обработки:

     Prices <- sample(1:10, 70, replace = TRUE) # dummy data
     [1] 10  1  1  9  9  6  6  9  7  3  6  4 10  4  8  6  6  9  2  1  6  4  7 10  1  6  5  2  7  7  4  6  7  7  7
    [36]  2  8  5  4  8  4  7  7  1  7  5  9  6  7  3 10  5 10  1  2  5  1  1  8  5  8  8  6  8  6  8 10  4  8  8
    matPrices <- matrix(Prices, ncol = 10)
     [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10]
[1,]   10    9    8    4    7    2    7    3    1     8
[2,]    1    7    6    7    7    8    1   10    1     6
[3,]    1    3    6   10    4    5    7    5    8     8
[4,]    9    6    9    1    6    4    5   10    5    10
[5,]    9    4    2    6    7    8    9    1    8     4
[6,]    6   10    1    5    7    4    6    2    8     8
[7,]    6    4    6    2    7    7    7    5    6     8
    matcummax <- apply(matPrices, 2, cummax)
     [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10]
[1,]   10    9    8    4    7    2    7    3    1     8
[2,]   10    9    8    7    7    8    7   10    1     8
[3,]   10    9    8   10    7    8    7   10    8     8
[4,]   10    9    9   10    7    8    7   10    8    10
[5,]   10    9    9   10    7    8    9   10    8    10
[6,]   10   10    9   10    7    8    9   10    8    10
[7,]   10   10    9   10    7    8    9   10    8    10
 

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

1. Хорошо, спасибо за ваш ответ. Это сработало для тех выборочных данных, которые я предоставил. Однако, поскольку я хочу «вычислить максимальное значение для каждых семи чисел», тогда это решение не будет расширяемо до большего фрейма данных, верно?

2. cummax Функция может быть расширена до любой длины. Что еще ты пытаешься сделать?

3. Извините, возможно, я недостаточно ясно выразился. Я пытался получить максимальное значение цены для каждой группы из семи последовательных значений. Я полагаю , что существует также действительное и хорошее решение этой проблемы с cummax помощью . Это также может быть полезно для меня и других пользователей, чтобы узнать об этом. Но мой вопрос касался конкретно поведения slide() функции при решении моей проблемы.

4. ОК. Я присоединяюсь к пословице Эйнштейна при написании кода: «Все должно быть сделано как можно проще, но не проще» Пример Multi cummax обновленный ответ.

5. Вы, без сомнения, правы. Спасибо за ваше время и ответ ( 1). Будет ли этот код вычислять максимум для каждой группы из 7 значений, несмотря на столбец, к которому я его применяю?