# En caso que no esté instalado 'dplyr' primero ejecutar install.package("dplyr")
library(dplyr)
# Creación de datos
<- data.frame("Nombre" = c("Carla", "Daniela", "Sergio", "Yanel"),
ejemplo "Valor A" = c(12, 8, 300, 17),
"Valor B" = c(5, 21, 18, 400),
"Valor C" = c(39, 200, 26, 64),
"Valor D" = c(100, 43, 86, 12))
Extraer el máximo valor de una fila
En este pequeño tutorial (por eso el tag de tipito
, o sea un tip chiquito), voy a contar cómo resolví un problema que me encontré en el trabajo y me trajo más de un dolor de cabeza.
Estaba trabajando con una tabla en la que tenía varios cursos, con sus fechas de finalización, y para el análisis que estaba haciendo necesitaba extraer la fecha del último curso completado por cada persona (el valor más alto).
El problema es que cuando estaba ejecutando la función max()
en vez de obtener el valor más alto de la fila, obtenía el valor más alto de la columna. Así que en este post vamos a ver la función rowwise()
que permite resolver este inconveniente.
En este ejemplo vamos a reemplazar las fechas por un número, que a los fines prácticos plantea el mismo problema.
Datos de ejemplo
Primero carguemos la librería dplyr
que además de contener la función rowwise()
nos permite trabajar con el pipe %>%
para simplificar la lectura del código. Luego crearemos un data frame de ejemplo con datos inventados
Ahora veamos cómo quedan los datos
# Ejecutar para ver el contenido del data frame
ejemplo
Nombre Valor.A Valor.B Valor.C Valor.D
1 Carla 12 5 39 100
2 Daniela 8 21 200 43
3 Sergio 300 18 26 86
4 Yanel 17 400 64 12
Lo que necesitaba lograr (en un archivo con muchas más columnas que en este ejemplo) es poner en una columna nueva el valor más alto para cada persona. Entonces para Carla
esperaba que el resultado fuera 100
, para Daniela
200
y así sucesivamente.
Instintivamente lo que hice para intentar obtener el valor más alto de cada caso, fue usar dentro de una función mutate()
(para crear una columna nueva) la función max()
a un vector con los nombres de las 4 columnas.
%>%
ejemplo mutate("Valor Máximo" = max(c(Valor.A, Valor.B, Valor.C, Valor.D)))
Nombre Valor.A Valor.B Valor.C Valor.D Valor Máximo
1 Carla 12 5 39 100 400
2 Daniela 8 21 200 43 400
3 Sergio 300 18 26 86 400
4 Yanel 17 400 64 12 400
Claramente no es es el resultado que esperaba, así que mi reacción fue la siguiente:
La solución
El problema del enfoque anterior es que la función max()
busca entre todos los datos que le pasamos, las 4 columnas con los valores numéricos, y lo que nos devuelve el valor máximo de entre todas las celdas. Este es un claro ejemplo de que R está haciendo lo que le dijimos que haga, no lo que estábamos queriendo que haga.
Para resolver esto, antes de crear una columna nueva con mutate()
, usamos la función rowwise()
.
%>%
ejemplo rowwise() %>% # Con esta función indicamos que queremos los cálculos sobre las filas
mutate("Valor Máximo" = max(c(Valor.A, Valor.B, Valor.C, Valor.D)))
# A tibble: 4 × 6
# Rowwise:
Nombre Valor.A Valor.B Valor.C Valor.D `Valor Máximo`
<chr> <dbl> <dbl> <dbl> <dbl> <dbl>
1 Carla 12 5 39 100 100
2 Daniela 8 21 200 43 200
3 Sergio 300 18 26 86 300
4 Yanel 17 400 64 12 400
La función rowwise()
lo que nos permite hacer es cálculos sobre las filas. Dependiendo el caso de uso se puede usar esta alternativa, o “pivotear” o transponer la tabla para que las columnas queden dentro de las filas y luego combinar group_by()
y summarise()
para calcular el valor máximo para cada persona.
Este enfoque sería así:
library(tidyr)
<- ejemplo %>%
ejemplo_largo # Pivoteamos los datos a un formato 'largo'
pivot_longer(cols = c("Valor.A", "Valor.B", "Valor.C", "Valor.D"),
names_to = "Variable",
values_to = "Valor")
# Veamos el dataset transformado
ejemplo_largo
# A tibble: 16 × 3
Nombre Variable Valor
<chr> <chr> <dbl>
1 Carla Valor.A 12
2 Carla Valor.B 5
3 Carla Valor.C 39
4 Carla Valor.D 100
5 Daniela Valor.A 8
6 Daniela Valor.B 21
7 Daniela Valor.C 200
8 Daniela Valor.D 43
9 Sergio Valor.A 300
10 Sergio Valor.B 18
11 Sergio Valor.C 26
12 Sergio Valor.D 86
13 Yanel Valor.A 17
14 Yanel Valor.B 400
15 Yanel Valor.C 64
16 Yanel Valor.D 12
# Ahora hacemos el cálculo combinando 'group_by' y 'summarise'
%>%
ejemplo_largo group_by(Nombre) %>%
summarise("Valor Máximo" = max(Valor))
# A tibble: 4 × 2
Nombre `Valor Máximo`
<chr> <dbl>
1 Carla 100
2 Daniela 200
3 Sergio 300
4 Yanel 400
Claramente este es otro enfoque, y depende de la necesidad es una opción válida. Pero en este caso particular necesitaba mantener una fila para cada persona porque después iba a exportar esta tabla a un archivo que luego es cargado en un tablero en Power BI.
Así que, una vez logrado mi objetivo, me dispuse a celebrar como corresponde.