¿Cómo evitar que la función slide () calcule un vector numérico en una lista?

Nov 25 2020

Tengo una data.framede una columna:

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

Quiero calcular el valor máximo de cada siete números, lo que da como resultado:

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

Sin embargo, cuando intento calcular esta nueva columna con mutate()y slide(), me devuelve una lista dentro del marco de datos, en lugar de una variable numérica:

library(dplyr)
library(slider)

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

¿Por qué sucede esto y cómo hacer que se slide()devuelva una variable numérica?

Respuestas

3 akrun Nov 25 2020 at 20:18

Parece que el método predeterminado solicita la listsalida. De acuerdo a?slide

vec_ptype (diapositiva (.x)) == lista ()

y la descripción de .ptypees

.ptype - [vector (0) / NULL]

Un prototipo correspondiente al tipo de salida.

Si es NULL, el valor predeterminado, el tipo de salida se determina calculando el tipo común en los resultados de las llamadas a .f.

Si se proporciona, el resultado de cada llamada a .f se convertirá en ese tipo y la salida final tendrá ese tipo.

Si getOption ("vctrs.no_guessing") es TRUE, se debe proporcionar el .ptype. Esta es una forma de hacer que el código de producción exija tipos fijos.

En esencia basado en el código fuente (abajo), es por defecto el retorno de una listy no parece haber ninguna opción para evitar que a menos que se opta por métodos específicos descritos es decir, _veco_dbl

O podríamos 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

O use el método específico del tipo, es decir 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

Si revisamos el código fuente de slide, llama slide_imply asume que .ptypeas listy no hay opción para pasar esa información enslide

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)
}

Ahora, compare eso con el _dblmétodo

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 SteveM Nov 25 2020 at 21:01

Puedes usar la cummaxfunción en la base R:

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

Para caso de múltiples vectores. Cargue el vector de datos en una matriz y aplique cummax a las columnas. Genera una matriz de vectores cummax para el tratamiento de seguimiento:

    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