Quiero reemplazar apply() (y sus derivados) con una función purrr.

Tengo un data.frame como este:

> df
  V1 V2 V3
1 NA  2  3
2  2 NA  3
3  3  3 NA

Y quiero aplicar dos funciones rowwise: min(x, na.rm = T) y which.min(x) y devolver los resultados como un marco de datos.

Si sé cuántas columnas hay, puedo hacer, p. esta:

pmap_dfr(df, function(V1, V2, V3) {data.frame(min = pmin(V1, V2, V3, na.rm = T),
                                              where = which.min(c(V1, V2, V3)))})

  min where
1   2     2
2   2     1
3   3     1

¿Cómo puedo hacer que pmap() o cualquier otra función purrr tome toda la fila como argumento al igual que apply()?

func <- function(x) {data.frame(min = min(x, na.rm = T), where = which.min(x))}

> Reduce(rbind, apply(df,1, func))
    min where
V2    2     2
V1    2     1
V11   3     1


Probablemente me perdí una característica o algún truco. Gracias por tu ayuda.

5
Humpelstielzchen 10 may. 2019 a las 11:54

3 respuestas

La mejor respuesta

Su solución funcionará para todas las columnas si usa puntos suspensivos.

pmap_dfr(df, ~data.frame(min = min(..., na.rm = TRUE), where = which.min(c(...)))) 

  min where
1   2     2
2   2     1
3   3     1
3
H 1 10 may. 2019 a las 10:25

No es una solución purrr, sino una línea data.table.

library(data.table)

dt <- fread("row V1 V2 V3
1 NA  2  3
2  2 NA  3
3  3  3 NA")

melt(dt, id.vars = "row")[ , .SD[which.min(value)], by = row]
   row variable value
1:   1       V2     2
2:   2       V1     2
3:   3       V1     3
1
Wimpel 10 may. 2019 a las 09:58

Una posibilidad podría ser:

df %>%
 mutate(min = invoke(pmin, na.rm = TRUE, .),
        where = max.col(!is.na(-.)[, 1:length(.)], ties.method = "first"))

  V1 V2 V3 min where
1 NA  2  3   2     2
2  2 NA  3   2     1
3  3  3 NA   3     1

O si desea mantener solo las últimas dos columnas:

df %>%
 transmute(min = invoke(pmin, na.rm = TRUE, .),
        where = max.col(!is.na(-.)[, 1:length(.)], ties.method = "first"))
2
tmfmnk 10 may. 2019 a las 09:22