R que R

Data Wrangling: Funciones de dplyr (Primera Parte)

Tue, Jun 9, 2020
R Data Wrangling
#dplyr #tidyverse


0. Paquetes e Introducción



library(dplyr)
library(tibble)
library(DT)
library(stringr)


El primer post de este blog, escrito en octubre de 2019, se centró en explicar las funciones básicas del paquete {dplyr} utilizando para los respectivos ejemplos los nombres de los recién nacidos en EEUU del paquete {babynames}. En dicho post se explicaban las funciones: select(), filter(), group_by(), mutate(), summarise() y arrange(). Como vimos, este conjunto de herramientas facilitan enormemente la manipulación de dataframes y tibbles y se configuran como una de los principales componentes del entorno o del conjunto de paquetes denominado tidyverse. Sin embargo, a estas alturas considero que va siendo hora de completar la información del post mencionado, agregando nuevas posibilidades del paquete {dplyr}, especialmente teniendo en cuenta que desde hace unos días tenemos disponible la nueva versión 1.0.0. Por ello, la finalidad principal que tiene este post será profundizar en las posibilidades que ofrece este paquete aunque, de hecho, la información que se va a exponer en los próximos apartados no va a ser mayor que la que se puede encontrar en la página de tidyverse. Espero, sin embargo, que la redacción de esta entrada me permita descubrir nuevas funcionalidades desconocidas por hasta el momento y practicar con las herramientas disponibles. Además, si el resultado acaba siendo útil no solo para mí, sino también para algún otro lector interesado, entonces la redacción de este post habrá sido provechosa.


El post se articulará siguiendo una clasificación similar al que sigue el cheatsheet del paquete dplyr. Utilizaré ejemplos de mi cosecha y, cuando sea posible, intentaré completar la información presentada en el mencionado cheatsheet con información adicional. Así que, sin más demora, vamos a ello.


1. Summarise Cases


Vamos a construir un ejemplo sencillo. Pongamos que tenemos dos variables VarA y VarB para cinco observaciones que serán cinco países (España, Italia, Portugal, Francia y Alemania). Creamos este dataframe y lo denominamos df. Téngase en cuenta que estos resultados son completamente inventados y aleatorios y no responden a ninguna realidad, variable o indicador real.



Names <- c("Spain", "Italy", "Portugal", "France", "Germany")
VarA  <- c(120, 110, 80, 145, 105)
VarB  <- c(1250, 890, 1550, 2340, 3200)

df <- tibble(Names, VarA, VarB)


datatable(df)


1.1. summarise()

Como ya vimos en el post anterior, la función summarise() nos devuelve un dataframe tipo tibble, en función de un conjunto de valores originales. De esta forma, podemos utilizar esta función para obtener el promedio de una de nuestras variables (VarA, VarB), o de ambas.



# El promedio de la variable VarA:

df %>%
  summarise(avg = mean(VarA))
## # A tibble: 1 x 1
##     avg
##   <dbl>
## 1   112


# El promedio de las variables VarA y VarB:

df %>%
  summarise(avgA = mean(VarA), 
            avgB = mean(VarB))
## # A tibble: 1 x 2
##    avgA  avgB
##   <dbl> <dbl>
## 1   112  1846


Existen numerosos indicadores que podemos aplicar junto con la función summarise(). Por ejemplo, podemos aplicar medidas de tendencia central, como son el promedio o la mediana:


  • mean()
  • median()



df %>%
  summarise(media = mean(VarA),
            median = median(VarA))
## # A tibble: 1 x 2
##   media median
##   <dbl>  <dbl>
## 1   112    110

 

O medidas de dispersión como la desviación estándar, la varianza, el rango intercuantílico o la desviación absoluta mediana:


  • sd()
  • var()
  • IQR()
  • mad()



df %>%
  summarise(desv.estandar = sd(VarA),
            varianza = var(VarA),
            IQR = IQR(VarA),
            mad = mad(VarA))
## # A tibble: 1 x 4
##   desv.estandar varianza   IQR   mad
##           <dbl>    <dbl> <dbl> <dbl>
## 1          23.6     558.    15  14.8


Además del rango intercuantílico (IQR), podemos fácilmente obtener los cuantiles de la distribución. En nuestro dataset, debido a su pequeño tamaño, esta operación carece de mucho significado pero la operativa sería la siguiente:


  • quantile()



df %>%
  summarise(QVarA = quantile(VarA, c(0.25, 0.5, 0.75)),
            QVarB = quantile(VarB, c(0.25, 0.5, 0.75)))
## # A tibble: 3 x 2
##   QVarA QVarB
##   <dbl> <dbl>
## 1   105  1250
## 2   110  1550
## 3   120  2340


Algunas de las funciones más populares, presentes en el paquete base de R, nos permiten identificar el valor máximo, el valor mínimo o estimar la suma del conjunto de observaciones:


  • min()
  • max()
  • sum()



df %>%
  summarise(minimo = min(VarA),
            maximo = max(VarA), 
            suma = sum(VarA))
## # A tibble: 1 x 3
##   minimo maximo  suma
##    <dbl>  <dbl> <dbl>
## 1     80    145   560


El paquete {dplyr} añade un conjunto de funciones para identificar la posición de las observaciones en el dataset. Podemos, por ejemplo, identificar el primer valor, el último o especificar qué valor queremos que nos devuelva (por ejemplo, pongamos que queremos obtener la tercera observación de la columna Names)


  • first()
  • last()
  • nth()



df %>%
  summarise(primero = first(VarA),
            ultimo = last(VarA), 
            tercero = nth(Names, 3))
## # A tibble: 1 x 3
##   primero ultimo tercero 
##     <dbl>  <dbl> <chr>   
## 1     120    105 Portugal


Otro tipo de operadores nos permiten contar las observaciones, bien sea el número total o el número de observaciones distintas o únicas. Como en nuestro dataset no hay países repetidos el resultado de ambas funciones al contar el número de observaciones y el número único de países será el mismo.


  • n()
  • n_distinct()



df %>%
  summarise(n = n(),
            ndistinto = n_distinct(Names))
## # A tibble: 1 x 2
##       n ndistinto
##   <int>     <int>
## 1     5         5


Con summarise() podemos utilizar también los operadores lógicos any y all. El primero de ellos nos indica si hay algún valor que cumpla algún requisito, devolviéndonos TRUE o FALSE como resultado. El segundo nos indica si todos los valores cumplen el requisito especificado, también devolviéndonos TRUE o FALSE. Por consiguiente, suponiendo que nos interese saber si alguno de los países tiene un VarA menor que 100 y, por otro lado, si todos los países registran un valor de dicho indicador menor que 500, el resultado sería:



df %>%
  summarise(any(VarA<100))
## # A tibble: 1 x 1
##   `any(VarA < 100)`
##   <lgl>            
## 1 TRUE


df %>%
  summarise(all(VarA<500))
## # A tibble: 1 x 1
##   `all(VarA < 500)`
##   <lgl>            
## 1 TRUE


Con summarise() podemos también estimar la correlación existente entre variables utilizando la función cor(). Así, por ejemplo, la correlación entre la variable VarA y la variable VarB de nuestro conjunto de datos sería:


  • cor()



df %>%
  summarize(correlacion = cor(VarA, VarB))
## # A tibble: 1 x 1
##   correlacion
##         <dbl>
## 1       0.154


Las posibilidades que nos ofrece summarise() a la hora de manejar nuestros datos son enormes, y se amplifican mucho más al combinar toda esta operativa con group_by() como veremos próximamente.


1.1.b. summarise_all(), summarise_at() y summarise_if()

Además de la función summarise(), existen otras variaciones que pueden resultar muy útiles a la hora de manejar datasets: summarise_all(), summarise_at() y summarise_if(). La primera de ellas, la función summarise_all(), permite aplicar una función a todas las variables de nuestro dataset. En nuestro caso esta función nos devolverá un warning debido a que la primera columna es de tipo character. La segunda función, la función summarise_at(), nos permite aplicar una operación a las columnas que nosotros indiquemos. Podemos, por ejemplo, estimar el promedio solo a las columnas dos y tres. En tercer lugar, la función summarise_if() realizará una operación atendiendo a una condición especificada en el comando. Por ejemplo, supongamos que queremos estimar el promedio, pero solo sobre las columnas que son de tipo numérico. Veamos la aplicación práctica de las tres funciones en nuestro pequeño dataset:



df %>%
  summarise_all(mean)
## Warning in mean.default(Names): argument is not numeric or logical: returning NA
## # A tibble: 1 x 3
##   Names  VarA  VarB
##   <dbl> <dbl> <dbl>
## 1    NA   112  1846

df %>%
  summarise_at(c("VarA", "VarB"), mean)
## # A tibble: 1 x 2
##    VarA  VarB
##   <dbl> <dbl>
## 1   112  1846

df %>%
  summarise_if(is.numeric, mean)
## # A tibble: 1 x 2
##    VarA  VarB
##   <dbl> <dbl>
## 1   112  1846


Aplicado a nuestro dataset el resultado obtenido es similar, aunque la lógica subyacente es distinta, y puede ser de gran utilidad cuando trabajamos con datasets de mayor tamaño.


La versión 1.0.0 del paquete {dplyr} ofrece otra posibilidad que se asemeja a summarise_at(). Con el comando across podemos indicar las columnas sobre las que queremos aplicar la operación y las funciones a aplicar a cada una de ellas.



df %>%
  summarise(across(c("VarA", "VarB"), mean))
## # A tibble: 1 x 2
##    VarA  VarB
##   <dbl> <dbl>
## 1   112  1846

df %>%
  summarise(across(c("VarA", "VarB"), list(mean = mean, median = median, sd = sd)))
## # A tibble: 1 x 6
##   VarA_mean VarA_median VarA_sd VarB_mean VarB_median VarB_sd
##       <dbl>       <dbl>   <dbl>     <dbl>       <dbl>   <dbl>
## 1       112         110    23.6      1846        1550    927.


Por otra parte, podemos combinar la condicionalidad de summarise_if() con más de una función a la vez pero en ese caso sería conveniente modificar el nombre de las columnas del dataframe resultante.



df %>%
  summarise_if(is.numeric, c(min, max))
## # A tibble: 1 x 4
##   VarA_fn1 VarB_fn1 VarA_fn2 VarB_fn2
##      <dbl>    <dbl>    <dbl>    <dbl>
## 1       80      890      145     3200


Nótese que igual que hemos utilizado is.numeric, podemos hacer uso de otros comandos como is.integer, is.double, is.logical, is.factor, is.POSIXt o is.Date (estos dos últimos requieren cargar el paquete {lubridate})


1.2. Count()

La función count() nos devuelve una columna con el número de observaciones de la variable indicada. Como en nuestro caso no tenemos valores repetidos, la función count() nos devolverá una columna indicando que únicamente existe una observación para cada país de la variable Names. Esta función se complementa perfectamente con n() y n_distinct() vistos anteriormente



df %>%
  count(Names, sort = TRUE)
## # A tibble: 5 x 2
##   Names        n
##   <chr>    <int>
## 1 France       1
## 2 Germany      1
## 3 Italy        1
## 4 Portugal     1
## 5 Spain        1


2. Group Cases: group_by()


La función group_by() convierte el dataframe original en una tabla agrupada según los parámetros de la función. Como ya hemos señalado, group_by() funciona muy bien cuando se utiliza conjuntamente con summarise(), pero también con otras funciones como puede ser mutate(). Para ejemplificar su funcionamiento vamos a crear un nuevo dataframe con una nueva columna que se llamará Type, y que nos servirá para agrupar las observaciones en tres categorías: A, B y C.



Names <- c("Spain", "Italy", "Portugal", "France", "Germany", "Greece", "Ireland", "Spain")
Type  <- c("A", "A", "C", "B", "B", "A", "C", "B")
VarA  <- c(120, 110, 80, 145, 105, 203, 345, 343)
VarB  <- c(1250, 890, 1550, 2340, 3200, 4938, 4923, 3423)


df <- tibble(Names, Type, VarA, VarB)

datatable(df)


Supongamos que queremos estimar el promedio y el valor máximo de la variable VarA pero según las categorías indicadas en la variable Type recién creada. En primer lugar agruparíamos las observaciones con group_by() y, a continuación, aplicaríamos summarise() como hemos visto previamente.



df %>%
  group_by(Type) %>%
  summarise(avg = mean(VarA),
            max = max(VarA)) %>% 
  ungroup()
## `summarise()` ungrouping output (override with `.groups` argument)
## # A tibble: 3 x 3
##   Type    avg   max
##   <chr> <dbl> <dbl>
## 1 A      144.   203
## 2 B      198.   343
## 3 C      212.   345


Podemos utilizar cualquiera de las herramientas previamente explicadas. Veamos algún ejemplo:



df %>%
  group_by(Type) %>%
  summarise_if(is.numeric, mean) %>%
  ungroup()
## # A tibble: 3 x 3
##   Type   VarA  VarB
##   <chr> <dbl> <dbl>
## 1 A      144. 2359.
## 2 B      198. 2988.
## 3 C      212. 3236.


df %>%
  group_by(Type) %>%
  summarise(tibble(min = min(VarA), max = max(VarA))) %>%
  ungroup()
## `summarise()` ungrouping output (override with `.groups` argument)
## # A tibble: 3 x 3
##   Type    min   max
##   <chr> <dbl> <dbl>
## 1 A       110   203
## 2 B       105   343
## 3 C        80   345


df %>%
  group_by(Type) %>%
  summarise(QVarA = quantile(VarA, c(0.25, 0.5, 0.75)),
            QVarB = quantile(VarB, c(0.25, 0.5, 0.75))) %>%
  ungroup()
## `summarise()` regrouping output by 'Type' (override with `.groups` argument)
## # A tibble: 9 x 3
##   Type  QVarA QVarB
##   <chr> <dbl> <dbl>
## 1 A      115  1070 
## 2 A      120  1250 
## 3 A      162. 3094 
## 4 B      125  2770 
## 5 B      145  3200 
## 6 B      244  3312.
## 7 C      146. 2393.
## 8 C      212. 3236.
## 9 C      279. 4080.


Nótese que podemos realizar más de una agrupación a la vez. En ese caso el orden en el que indicamos las categorías será de gran importancia. Veamos dos ejemplos. En el primero de ellos agrupamos en primer lugar por Type y en segundo lugar por Names mientras que en el segundo ejemplo agrupamos primero por Names y después por Type. El resultado estará ordenado alfabéticamente según el orden establecido.



df %>%
  group_by(Type, Names) %>%
  summarise(mean =max(VarA)) %>%
  ungroup()
## `summarise()` regrouping output by 'Type' (override with `.groups` argument)
## # A tibble: 8 x 3
##   Type  Names     mean
##   <chr> <chr>    <dbl>
## 1 A     Greece     203
## 2 A     Italy      110
## 3 A     Spain      120
## 4 B     France     145
## 5 B     Germany    105
## 6 B     Spain      343
## 7 C     Ireland    345
## 8 C     Portugal    80

df %>%
  group_by(Names, Type) %>%
  summarise(mean =max(VarA)) %>%
  ungroup()
## `summarise()` regrouping output by 'Names' (override with `.groups` argument)
## # A tibble: 8 x 3
##   Names    Type   mean
##   <chr>    <chr> <dbl>
## 1 France   B       145
## 2 Germany  B       105
## 3 Greece   A       203
## 4 Ireland  C       345
## 5 Italy    A       110
## 6 Portugal C        80
## 7 Spain    A       120
## 8 Spain    B       343


3. Manipulate Cases


En este apartado se expondrán las herramientas de {dplyr} diseñadas para extraer, ordenar o añadir observaciones en función del dataset original. Para ello vamos a crear un nuevo dataframe, similar a los anteriores, pero donde tengamos más filas y un mayor número de repeticiones.



Names <- c("Spain", "Italy", "Portugal", "France", "Germany", "Spain", "Italy", "Portugal", "Spain", "Ireland")
VarA  <- c(120, 110, 80, 145, 105, 340, 345, 542, 237, 543)
VarB  <- c(1250, 890, 1550, 2340, 3200, 530, 345, 321, 345, 453)

df <- tibble(Names, VarA, VarB)

datatable(df)


3.1. Extract Cases

3.1.1. filter()


En primer lugar vamos a presentar las herramientas que nos permiten extraer observaciones (filas) del dataset original. La primera de ellas, la función filter(), es tremendamente útil en tanto que nos permite seleccionar el conjunto de observaciones según un determinado criterio. Las situaciones donde esta herramienta sirve de gran ayuda son numerosas. Por ejemplo, pongamos que queremos seleccionar los países que tienen un valor menor a 80 en la variable VarA, o solamente nos interesa seleccionar aquellas observaciones referentes a España. Puede que queramos identificar las observaciones para dos países específicos, o identificar las variables para aquellos países cuyos nombres se encuentren en un lista predeterminada. Veamos entonces cómo podríamos realizar operaciones de este estilo utilizando operadores relacionales y lógicos como: <, >, >=, <=, ==, between, |, &, %in%, !, is.na, !is.na, xor, any, all:


Países con VarA menor que 100 (<):



df %>%
  filter(VarA < 100)
## # A tibble: 1 x 3
##   Names     VarA  VarB
##   <chr>    <dbl> <dbl>
## 1 Portugal    80  1550


Países con VarA menor o igual que 110 (>):



df %>%
  filter(VarA <= 110)
## # A tibble: 3 x 3
##   Names     VarA  VarB
##   <chr>    <dbl> <dbl>
## 1 Italy      110   890
## 2 Portugal    80  1550
## 3 Germany    105  3200


Países con VarA mayor que 500 (<=):



df %>%
  filter(VarA > 500)
## # A tibble: 2 x 3
##   Names     VarA  VarB
##   <chr>    <dbl> <dbl>
## 1 Portugal   542   321
## 2 Ireland    543   453


Países con VarA mayor o igual que 340 (>=):



df %>%
  filter(VarA >= 340)
## # A tibble: 4 x 3
##   Names     VarA  VarB
##   <chr>    <dbl> <dbl>
## 1 Spain      340   530
## 2 Italy      345   345
## 3 Portugal   542   321
## 4 Ireland    543   453


Países con VarA entre 100 y 400 (between):



df %>%
  filter(between(VarA, 100, 400))
## # A tibble: 7 x 3
##   Names    VarA  VarB
##   <chr>   <dbl> <dbl>
## 1 Spain     120  1250
## 2 Italy     110   890
## 3 France    145  2340
## 4 Germany   105  3200
## 5 Spain     340   530
## 6 Italy     345   345
## 7 Spain     237   345


Solo un país en concreto (==):



df %>%
  filter(Names == "Spain")
## # A tibble: 3 x 3
##   Names  VarA  VarB
##   <chr> <dbl> <dbl>
## 1 Spain   120  1250
## 2 Spain   340   530
## 3 Spain   237   345


Solo dos países, o uno u otro (|):



df %>%
  filter(Names == "Spain" | Names == "Portugal")
## # A tibble: 5 x 3
##   Names     VarA  VarB
##   <chr>    <dbl> <dbl>
## 1 Spain      120  1250
## 2 Portugal    80  1550
## 3 Spain      340   530
## 4 Portugal   542   321
## 5 Spain      237   345


Países que cumplan solo una de las dos condiciones (xor):



df %>%
  filter(xor(VarA >500, VarB < 500))
## # A tibble: 2 x 3
##   Names  VarA  VarB
##   <chr> <dbl> <dbl>
## 1 Italy   345   345
## 2 Spain   237   345


Países cuya inicial aparezca en el alfabeto después de la letra “p”:



df %>%
  filter(Names > "p")
## # A tibble: 5 x 3
##   Names     VarA  VarB
##   <chr>    <dbl> <dbl>
## 1 Spain      120  1250
## 2 Portugal    80  1550
## 3 Spain      340   530
## 4 Portugal   542   321
## 5 Spain      237   345


Solo valores para España y que su VarA sea mayor a 200 (&):



df %>%
  filter(Names == "Spain" & VarA > 200)
## # A tibble: 2 x 3
##   Names  VarA  VarB
##   <chr> <dbl> <dbl>
## 1 Spain   340   530
## 2 Spain   237   345


Solo países incluidos en una lista “x” (%in%):



x <- c("Albania", "Austria", "United Kingdom", "France", "Norway", "Morocco", "Italy", "Poland", "Croatia")

df %>%
  filter(Names %in% x)
## # A tibble: 3 x 3
##   Names   VarA  VarB
##   <chr>  <dbl> <dbl>
## 1 Italy    110   890
## 2 France   145  2340
## 3 Italy    345   345


Todos los países excluyendo uno (!):



df %>%
  filter(Names != "Spain")
## # A tibble: 7 x 3
##   Names     VarA  VarB
##   <chr>    <dbl> <dbl>
## 1 Italy      110   890
## 2 Portugal    80  1550
## 3 France     145  2340
## 4 Germany    105  3200
## 5 Italy      345   345
## 6 Portugal   542   321
## 7 Ireland    543   453


Podemos necesitar todos los valores cercanos a un determinado valor. Para ello utilizamos a función near() indicando un grado de tolerancia (tol):



df %>%
  filter(near(VarA, 100, tol = sd(VarA)))
## # A tibble: 6 x 3
##   Names     VarA  VarB
##   <chr>    <dbl> <dbl>
## 1 Spain      120  1250
## 2 Italy      110   890
## 3 Portugal    80  1550
## 4 France     145  2340
## 5 Germany    105  3200
## 6 Spain      237   345


Aunque en nuestro dataset no tenemos NA's es común que se de el caso. Por ello las funciones is.na y !is.na suelen ser muy utilizadas. La primera de ellas nos devolverá un tibble con los valores que contienen NA's mientras que la segunda nos devuelve los que no contienen NA's. Evidentemente en nuestro caso el primer tibble estará vacío al no contener valores NA.



df %>%
  filter(is.na(VarA))
## # A tibble: 0 x 3
## # ... with 3 variables: Names <chr>, VarA <dbl>, VarB <dbl>

df %>%
  filter(!is.na(VarA))
## # A tibble: 10 x 3
##    Names     VarA  VarB
##    <chr>    <dbl> <dbl>
##  1 Spain      120  1250
##  2 Italy      110   890
##  3 Portugal    80  1550
##  4 France     145  2340
##  5 Germany    105  3200
##  6 Spain      340   530
##  7 Italy      345   345
##  8 Portugal   542   321
##  9 Spain      237   345
## 10 Ireland    543   453


3.1.1.b. filter_all(), filter_at() y filter_if()


Supongamos que queremos que nuestro comando nos devuelva cualquier observación que tenga en alguna de sus columnas un valor inferior a 100 o que nos devuelva las filas donde todas las variables cumplan un determinado requisito, por ejemplo los países donde tanto VarA como VarB sean mayores que 300. Para ello resulta de gran utilidad hacer uso de filter_all() junto con los comandos any_vars y/o all_vars.


  • filter_all()



# Alguna de las observaciones con valor inferior a 100:

df %>%
  filter_all(any_vars(. <100))
## # A tibble: 1 x 3
##   Names     VarA  VarB
##   <chr>    <dbl> <dbl>
## 1 Portugal    80  1550

# Todas las columnas con valores inferiores a 300:

df %>%
  filter_all(all_vars(. >300))
## # A tibble: 4 x 3
##   Names     VarA  VarB
##   <chr>    <dbl> <dbl>
## 1 Spain      340   530
## 2 Italy      345   345
## 3 Portugal   542   321
## 4 Ireland    543   453


Podría interesarnos en nuestro análisis que el comando nos devolviera las filas donde se encontrase una determinada palabra o unas determinadas letras, independientemente de la columna donde éstas se encontrasen. En nuestro caso solo tenemos una columna de tipo character y, por tanto, este ejemplo no lucirá como debería. No obstante, supongamos que queremos que nos devuelva las filas donde aparezcan las letras an. Para ello utilizaríamos las funciones del paquete {stringr} de la siguiente forma:



df %>%
  filter_all(any_vars(str_detect(., pattern = "an")))
## # A tibble: 3 x 3
##   Names    VarA  VarB
##   <chr>   <dbl> <dbl>
## 1 France    145  2340
## 2 Germany   105  3200
## 3 Ireland   543   453


La función filter_at() nos permite indicar qué columnas son las que deben cumplir el requisito establecido. De nuevo, como nuestro dataset solo se compone de dos columnas numéricas el ejemplo no va a lucir mucho, y los resultados serán similares a los realizados con filter_all, pero la dinámica está clara para ser aplicada a otros datasets. Podemos utilizar de nuevo all_vars y any_vars para indicar si la condición debe tener lugar en una de las columnas indicadas o en todas.


  • filter_at()



df %>%
  filter_at(vars(VarA, VarB), all_vars(. >300))
## # A tibble: 4 x 3
##   Names     VarA  VarB
##   <chr>    <dbl> <dbl>
## 1 Spain      340   530
## 2 Italy      345   345
## 3 Portugal   542   321
## 4 Ireland    543   453

df %>%
  filter_at(vars(VarA, VarB), any_vars(. >500))
## # A tibble: 8 x 3
##   Names     VarA  VarB
##   <chr>    <dbl> <dbl>
## 1 Spain      120  1250
## 2 Italy      110   890
## 3 Portugal    80  1550
## 4 France     145  2340
## 5 Germany    105  3200
## 6 Spain      340   530
## 7 Portugal   542   321
## 8 Ireland    543   453


La función filter_if() nos permite establecer qué características deben cumplir las variables sobre las que queremos aplicar nuestra condición de filtrado. Al igual que vimos en la función summarise(), puede que queramos aplicar el filtro solo a las columnas que sean de tipo factor, numeric, character, etc.. Pongamos que queremos aplicar el filtro solo a las variables de tipo numérico:



df %>%
  filter_if(is.numeric, all_vars(. >300))
## # A tibble: 4 x 3
##   Names     VarA  VarB
##   <chr>    <dbl> <dbl>
## 1 Spain      340   530
## 2 Italy      345   345
## 3 Portugal   542   321
## 4 Ireland    543   453

df %>%
  filter_if(is.numeric, any_vars(. >500))
## # A tibble: 8 x 3
##   Names     VarA  VarB
##   <chr>    <dbl> <dbl>
## 1 Spain      120  1250
## 2 Italy      110   890
## 3 Portugal    80  1550
## 4 France     145  2340
## 5 Germany    105  3200
## 6 Spain      340   530
## 7 Portugal   542   321
## 8 Ireland    543   453


3.1.2. distinct()


La función distinct() elimina del dataframe las filas con valores repetidos. Por ejemplo, si queremos identificar los países que se encuentran en la primera columna evitando que aparezcan valores repetidos podemos escribir lo siguiente:



df %>%
  distinct(Names)
## # A tibble: 6 x 1
##   Names   
##   <chr>   
## 1 Spain   
## 2 Italy   
## 3 Portugal
## 4 France  
## 5 Germany 
## 6 Ireland


Cabe la posibilidad de que queramos conservar los valores de las columnas correspondientes a los países resultantes. Para ello indicaremos .keep_all= TRUE. Como R elimina las observaciones repetidas, los valores devueltos de los países inicialmente repetidos serán los que se encuentren en primeras posiciones en el dataset original.



df %>%
  distinct(Names, .keep_all=TRUE)
## # A tibble: 6 x 3
##   Names     VarA  VarB
##   <chr>    <dbl> <dbl>
## 1 Spain      120  1250
## 2 Italy      110   890
## 3 Portugal    80  1550
## 4 France     145  2340
## 5 Germany    105  3200
## 6 Ireland    543   453

 

3.1.3. sample_frac() y sample_n()


sample_frac() y sample_n() son funciones que devuelven un determinado número de filas seleccionadas de forma aleatoria del dataset original. La primera de ellas, select_frac() devuelve un porcentaje (N%) de las filas mientras que sample_n() devuelve un número de filas que indiquemos en el comando. Por ejemplo, supongamos que queremos que seleccione el sesenta por ciento de nuestro dataset de forma aleatoria. En ese caso indicaremos lo siguiente:



df %>%
  sample_frac(0.6, replace = T)
## # A tibble: 6 x 3
##   Names     VarA  VarB
##   <chr>    <dbl> <dbl>
## 1 Portugal   542   321
## 2 Portugal    80  1550
## 3 Italy      345   345
## 4 Italy      345   345
## 5 Ireland    543   453
## 6 Germany    105  3200


O supongamos que nos interesa que seleccione únicamente tres filas escogidas al azar:



df %>%
  sample_n(3, replace = T)
## # A tibble: 3 x 3
##   Names     VarA  VarB
##   <chr>    <dbl> <dbl>
## 1 Portugal   542   321
## 2 Germany    105  3200
## 3 Germany    105  3200


replace = TRUE o replace = FALSE indicará si queremos que haya repeticiones entre las observaciones seleccionadas.


3.1.4. slice()


La función slice() permite seleccionar el conjunto de filas que queremos conservar. En cierta medida sería como realizar un corte en una tarta para quedarnos una cantidad determinada.



df %>%
  slice(3:6) 
## # A tibble: 4 x 3
##   Names     VarA  VarB
##   <chr>    <dbl> <dbl>
## 1 Portugal    80  1550
## 2 France     145  2340
## 3 Germany    105  3200
## 4 Spain      340   530


Podemos jugar con los signos + y -. Por ejemplo, supongamos que queremos conservar solo el valor de la fila 4 (Francia) o que, por el contrario, queremos conservar todas filas menos la fila 4.




df %>%
  slice(4)
## # A tibble: 1 x 3
##   Names   VarA  VarB
##   <chr>  <dbl> <dbl>
## 1 France   145  2340

df %>%
  slice(-4)
## # A tibble: 9 x 3
##   Names     VarA  VarB
##   <chr>    <dbl> <dbl>
## 1 Spain      120  1250
## 2 Italy      110   890
## 3 Portugal    80  1550
## 4 Germany    105  3200
## 5 Spain      340   530
## 6 Italy      345   345
## 7 Portugal   542   321
## 8 Spain      237   345
## 9 Ireland    543   453


Podemos también utilizar n() para ayudarnos a seleccionar las filas que nos interesa eliminar o conservar. n() representará el último valor, por lo que podemos utilizarlo para seleccionar la última fila del dataset o para seleccionar todas las observaciones hasta dicha fila.



df %>%
  slice(n())
## # A tibble: 1 x 3
##   Names    VarA  VarB
##   <chr>   <dbl> <dbl>
## 1 Ireland   543   453

df %>% 
  slice(3:n())
## # A tibble: 8 x 3
##   Names     VarA  VarB
##   <chr>    <dbl> <dbl>
## 1 Portugal    80  1550
## 2 France     145  2340
## 3 Germany    105  3200
## 4 Spain      340   530
## 5 Italy      345   345
## 6 Portugal   542   321
## 7 Spain      237   345
## 8 Ireland    543   453


Nótese que existen diversas combinaciones que pueden devolvernos el mismo resultado. Véase los dos ejemplos siguientes:



df %>%
  slice(-4:-n())
## # A tibble: 3 x 3
##   Names     VarA  VarB
##   <chr>    <dbl> <dbl>
## 1 Spain      120  1250
## 2 Italy      110   890
## 3 Portugal    80  1550

df %>%
  slice(1:3)
## # A tibble: 3 x 3
##   Names     VarA  VarB
##   <chr>    <dbl> <dbl>
## 1 Spain      120  1250
## 2 Italy      110   890
## 3 Portugal    80  1550


3.1.5. top_n()


Acabamos este subapartado con la función top_n(). Esta función selecciona un número determinado de filas con los valores de mayor (o menor) número según indiquemos en el código. Veamos por ejemplo cuáles son los dos países con mayor VarA y los dos países con menor VarB.



df %>%
  top_n(2, VarA)
## # A tibble: 2 x 3
##   Names     VarA  VarB
##   <chr>    <dbl> <dbl>
## 1 Portugal   542   321
## 2 Ireland    543   453

df %>%
  top_n(-2, VarB)
## # A tibble: 3 x 3
##   Names     VarA  VarB
##   <chr>    <dbl> <dbl>
## 1 Italy      345   345
## 2 Portugal   542   321
## 3 Spain      237   345

# Nos devuelve tres países porque dos de ellos tienen el mismo VarB


3.2. Arrange Cases: arrange()

La función arrange() permite ordenar las filas del dataset de forma ascendente o descendente según un valor numérico o siguiendo un criterio alfabético.



df %>%
  arrange(VarA)
## # A tibble: 10 x 3
##    Names     VarA  VarB
##    <chr>    <dbl> <dbl>
##  1 Portugal    80  1550
##  2 Germany    105  3200
##  3 Italy      110   890
##  4 Spain      120  1250
##  5 France     145  2340
##  6 Spain      237   345
##  7 Spain      340   530
##  8 Italy      345   345
##  9 Portugal   542   321
## 10 Ireland    543   453

df %>%
  arrange(desc(VarB))
## # A tibble: 10 x 3
##    Names     VarA  VarB
##    <chr>    <dbl> <dbl>
##  1 Germany    105  3200
##  2 France     145  2340
##  3 Portugal    80  1550
##  4 Spain      120  1250
##  5 Italy      110   890
##  6 Spain      340   530
##  7 Ireland    543   453
##  8 Italy      345   345
##  9 Spain      237   345
## 10 Portugal   542   321

df %>%
  arrange(Names)
## # A tibble: 10 x 3
##    Names     VarA  VarB
##    <chr>    <dbl> <dbl>
##  1 France     145  2340
##  2 Germany    105  3200
##  3 Ireland    543   453
##  4 Italy      110   890
##  5 Italy      345   345
##  6 Portugal    80  1550
##  7 Portugal   542   321
##  8 Spain      120  1250
##  9 Spain      340   530
## 10 Spain      237   345

df %>%
  arrange(desc(Names))
## # A tibble: 10 x 3
##    Names     VarA  VarB
##    <chr>    <dbl> <dbl>
##  1 Spain      120  1250
##  2 Spain      340   530
##  3 Spain      237   345
##  4 Portugal    80  1550
##  5 Portugal   542   321
##  6 Italy      110   890
##  7 Italy      345   345
##  8 Ireland    543   453
##  9 Germany    105  3200
## 10 France     145  2340


3.3. Add Cases: add_row()

La función add_row() permite añadir filas al dataset. Añadamos Bélgica a nuestro dataset:



df %>%
  add_row(Names = "Belgium", VarA = 89, VarB = 2800)
## # A tibble: 11 x 3
##    Names     VarA  VarB
##    <chr>    <dbl> <dbl>
##  1 Spain      120  1250
##  2 Italy      110   890
##  3 Portugal    80  1550
##  4 France     145  2340
##  5 Germany    105  3200
##  6 Spain      340   530
##  7 Italy      345   345
##  8 Portugal   542   321
##  9 Spain      237   345
## 10 Ireland    543   453
## 11 Belgium     89  2800


Vemos que Bélgica ha sido añadida como columna 11. No obstante, puede que nos interese situar esta observación en otro lugar del dataframe. Para ello podemos utilizar opciones como: .before = o .after =.



df %>%
  add_row(Names = "Belgium", VarA = 89, VarB = 2800, .before = 2)
## # A tibble: 11 x 3
##    Names     VarA  VarB
##    <chr>    <dbl> <dbl>
##  1 Spain      120  1250
##  2 Belgium     89  2800
##  3 Italy      110   890
##  4 Portugal    80  1550
##  5 France     145  2340
##  6 Germany    105  3200
##  7 Spain      340   530
##  8 Italy      345   345
##  9 Portugal   542   321
## 10 Spain      237   345
## 11 Ireland    543   453

df %>%
  add_row(Names = "Belgium", VarA = 89, VarB = 2800, .after = 2)
## # A tibble: 11 x 3
##    Names     VarA  VarB
##    <chr>    <dbl> <dbl>
##  1 Spain      120  1250
##  2 Italy      110   890
##  3 Belgium     89  2800
##  4 Portugal    80  1550
##  5 France     145  2340
##  6 Germany    105  3200
##  7 Spain      340   530
##  8 Italy      345   345
##  9 Portugal   542   321
## 10 Spain      237   345
## 11 Ireland    543   453


4. Manipulate Variables


El apartado anterior se ha centrado en exponer algunas herramientas disponibles en {dplyr} para manipular filas/ observaciones. En este apartado se expondrá cómo manipular variables/ columnas de un dataset. El primer bloque tratará sobre las herramientas disponibles para extraer variables y el segundo bloque se centrará en analizar cómo crear nuevas variables en función de las variables originales.


4.1. Extract Variables

4.1.1. pull()


La opción pull() extrae las observaciones indicadas y crea un vector. Por ejemplo, si queremos que R extraiga los nombres de los países escribiremos:



df %>%
  pull(Names)
##  [1] "Spain"    "Italy"    "Portugal" "France"   "Germany"  "Spain"   
##  [7] "Italy"    "Portugal" "Spain"    "Ireland"

# el resultado es el mismo que si escribimos:

df$Names
##  [1] "Spain"    "Italy"    "Portugal" "France"   "Germany"  "Spain"   
##  [7] "Italy"    "Portugal" "Spain"    "Ireland"


pull() funciona también con variables numéricas. Podemos, por ejemplo, indicar que extraiga una de nuestras variables, que extraiga la tercera columna del dataset o la primera columna empezando por el final.



df %>%
  pull(VarB)
##  [1] 1250  890 1550 2340 3200  530  345  321  345  453

df %>%
  pull(3)
##  [1] 1250  890 1550 2340 3200  530  345  321  345  453

df %>%
  pull(-1)
##  [1] 1250  890 1550 2340 3200  530  345  321  345  453


4.1.2. select()


La función select() tiene una utilidad similar a pull(), pero en lugar de devolver un vector devuelve un dataframe. Además, select() permite seleccionar varias columnas donde el orden en el que son seleccionadas influye en la configuración del dataframe resultante.



df %>%
  select(Names, VarB)
## # A tibble: 10 x 2
##    Names     VarB
##    <chr>    <dbl>
##  1 Spain     1250
##  2 Italy      890
##  3 Portugal  1550
##  4 France    2340
##  5 Germany   3200
##  6 Spain      530
##  7 Italy      345
##  8 Portugal   321
##  9 Spain      345
## 10 Ireland    453

df %>%
  select(VarA, Names)
## # A tibble: 10 x 2
##     VarA Names   
##    <dbl> <chr>   
##  1   120 Spain   
##  2   110 Italy   
##  3    80 Portugal
##  4   145 France  
##  5   105 Germany 
##  6   340 Spain   
##  7   345 Italy   
##  8   542 Portugal
##  9   237 Spain   
## 10   543 Ireland


Para seleccionar las columnas podemos utilizar algunas de las operaciones ya conocidas.



df %>%
  select(1,3)
## # A tibble: 10 x 2
##    Names     VarB
##    <chr>    <dbl>
##  1 Spain     1250
##  2 Italy      890
##  3 Portugal  1550
##  4 France    2340
##  5 Germany   3200
##  6 Spain      530
##  7 Italy      345
##  8 Portugal   321
##  9 Spain      345
## 10 Ireland    453

df %>%
  select(-2)
## # A tibble: 10 x 2
##    Names     VarB
##    <chr>    <dbl>
##  1 Spain     1250
##  2 Italy      890
##  3 Portugal  1550
##  4 France    2340
##  5 Germany   3200
##  6 Spain      530
##  7 Italy      345
##  8 Portugal   321
##  9 Spain      345
## 10 Ireland    453

df %>%
  select(2:3)
## # A tibble: 10 x 2
##     VarA  VarB
##    <dbl> <dbl>
##  1   120  1250
##  2   110   890
##  3    80  1550
##  4   145  2340
##  5   105  3200
##  6   340   530
##  7   345   345
##  8   542   321
##  9   237   345
## 10   543   453

df %>%
  select(!(2:3))
## # A tibble: 10 x 1
##    Names   
##    <chr>   
##  1 Spain   
##  2 Italy   
##  3 Portugal
##  4 France  
##  5 Germany 
##  6 Spain   
##  7 Italy   
##  8 Portugal
##  9 Spain   
## 10 Ireland

df %>%
  select(last_col())
## # A tibble: 10 x 1
##     VarB
##    <dbl>
##  1  1250
##  2   890
##  3  1550
##  4  2340
##  5  3200
##  6   530
##  7   345
##  8   321
##  9   345
## 10   453


4.1.2.b. Select Helpers


Existen ciertos comandos, conocidos como select helpers, que son de gran utilidad a la hora de establecer criterios para la selección de columnas. Comandos como contains(), starts_with() o end_width() nos permiten seleccionar columnas que empiecen, terminen o contengan algún caracter específico. Por su parte, el comando match() busca coincidencias que se ajusten a las indicaciones aplicadas a través de alguna expresión regular (regular expression).



df %>%
  select(contains("Var"))
## # A tibble: 10 x 2
##     VarA  VarB
##    <dbl> <dbl>
##  1   120  1250
##  2   110   890
##  3    80  1550
##  4   145  2340
##  5   105  3200
##  6   340   530
##  7   345   345
##  8   542   321
##  9   237   345
## 10   543   453

df %>%
  select(starts_with("Var"))
## # A tibble: 10 x 2
##     VarA  VarB
##    <dbl> <dbl>
##  1   120  1250
##  2   110   890
##  3    80  1550
##  4   145  2340
##  5   105  3200
##  6   340   530
##  7   345   345
##  8   542   321
##  9   237   345
## 10   543   453

df %>%
  select(ends_with("B"))
## # A tibble: 10 x 1
##     VarB
##    <dbl>
##  1  1250
##  2   890
##  3  1550
##  4  2340
##  5  3200
##  6   530
##  7   345
##  8   321
##  9   345
## 10   453

df %>%
  select(matches(".ar."))
## # A tibble: 10 x 2
##     VarA  VarB
##    <dbl> <dbl>
##  1   120  1250
##  2   110   890
##  3    80  1550
##  4   145  2340
##  5   105  3200
##  6   340   530
##  7   345   345
##  8   542   321
##  9   237   345
## 10   543   453


Con la función select() puede resultar de gran utilidad hacer uso de los comandos one_of, any_of o all_of. Pongamos que tenemos una lista con diversos nombres entre los que puede encontrarse alguna de las variables de nuestro dataset. En ese contexto puede resultar muy útil querer seleccionar las columnas de nuestro dataset que se corresponda con alguna o con todas las variables de dicha lista.



x <- c("Pepa", "Pepe", "VarA", "Pepi", "Names", "Pepo")

df %>%
  select(any_of(x))
## # A tibble: 10 x 2
##     VarA Names   
##    <dbl> <chr>   
##  1   120 Spain   
##  2   110 Italy   
##  3    80 Portugal
##  4   145 France  
##  5   105 Germany 
##  6   340 Spain   
##  7   345 Italy   
##  8   542 Portugal
##  9   237 Spain   
## 10   543 Ireland

# o lo que es lo mismo:

df %>%
  select(any_of(c("Pepa", "Pepe", "VarA", "Pepi", "Names", "Pepo")))
## # A tibble: 10 x 2
##     VarA Names   
##    <dbl> <chr>   
##  1   120 Spain   
##  2   110 Italy   
##  3    80 Portugal
##  4   145 France  
##  5   105 Germany 
##  6   340 Spain   
##  7   345 Italy   
##  8   542 Portugal
##  9   237 Spain   
## 10   543 Ireland



y <- c("VarA", "VarB")

df %>%
  select(all_of(y))
## # A tibble: 10 x 2
##     VarA  VarB
##    <dbl> <dbl>
##  1   120  1250
##  2   110   890
##  3    80  1550
##  4   145  2340
##  5   105  3200
##  6   340   530
##  7   345   345
##  8   542   321
##  9   237   345
## 10   543   453

# o lo que es lo mismo:

df %>%
  select(all_of(c("VarA", "VarB")))
## # A tibble: 10 x 2
##     VarA  VarB
##    <dbl> <dbl>
##  1   120  1250
##  2   110   890
##  3    80  1550
##  4   145  2340
##  5   105  3200
##  6   340   530
##  7   345   345
##  8   542   321
##  9   237   345
## 10   543   453


En ocasiones nos encontramos variables con nombres del estilo: (x01, x02, x03,…) o (Y2001, Y2002, Y2003,…). En estas ocasiones resulta de gran utilidad el comando num_range() para seleccionar dichas columnas. Esta función requiere que indiquemos el prefijo de las columnas y, posteriormente los valores a seleccionar. Veamos un ejemplo:



Names = c("Argentina", "Peru", "Bolivia", "Ecuador", "Brazil")
Y2001 = c(2345, 3456, 4567, 5678, 8901)
Y2002 = c(2456, 3567, 4678, 5789, 6890)
Y2003 = c(2567, 3678, 4890, 5789, 6234)
df2 <- tibble(Names, Y2001, Y2002, Y2003)


df2 %>%
  select(num_range("Y", 2001:2003))
## # A tibble: 5 x 3
##   Y2001 Y2002 Y2003
##   <dbl> <dbl> <dbl>
## 1  2345  2456  2567
## 2  3456  3567  3678
## 3  4567  4678  4890
## 4  5678  5789  5789
## 5  8901  6890  6234


4.1.2.c. select_all(), select_if(), select_at()


Alternativamente podemos utilizar las variantes select_all(), select_if() y select_at(). Entre otras cosas podemos seleccionar todas las variables y convertir los títulos a mayúscula o seleccionar solo las variables según su tipología (character, numeric, etc.). Podemos también seleccionar aquellas variables que contienen ciertos caracteres o que empiezan por una determinada letra. Veamos estos ejemplos:




df %>%
  select_all(toupper)
## # A tibble: 10 x 3
##    NAMES     VARA  VARB
##    <chr>    <dbl> <dbl>
##  1 Spain      120  1250
##  2 Italy      110   890
##  3 Portugal    80  1550
##  4 France     145  2340
##  5 Germany    105  3200
##  6 Spain      340   530
##  7 Italy      345   345
##  8 Portugal   542   321
##  9 Spain      237   345
## 10 Ireland    543   453

df %>%
  select_if(is.numeric)
## # A tibble: 10 x 2
##     VarA  VarB
##    <dbl> <dbl>
##  1   120  1250
##  2   110   890
##  3    80  1550
##  4   145  2340
##  5   105  3200
##  6   340   530
##  7   345   345
##  8   542   321
##  9   237   345
## 10   543   453

df %>%
  select_at(vars(-contains("ar")))
## # A tibble: 10 x 1
##    Names   
##    <chr>   
##  1 Spain   
##  2 Italy   
##  3 Portugal
##  4 France  
##  5 Germany 
##  6 Spain   
##  7 Italy   
##  8 Portugal
##  9 Spain   
## 10 Ireland

df %>%
  select_at(vars(starts_with("V")))
## # A tibble: 10 x 2
##     VarA  VarB
##    <dbl> <dbl>
##  1   120  1250
##  2   110   890
##  3    80  1550
##  4   145  2340
##  5   105  3200
##  6   340   530
##  7   345   345
##  8   542   321
##  9   237   345
## 10   543   453


4.2. Make New Variables

4.2.1. mutate() y transmute()


Para crear una nueva variable a partir del dataframe original podemos utilizar las funciones mutate() y transmute(). mutate() creará una nueva columna con el resultado deseado que se añadirá al dataframe mientras que la segunda, transmute() devolverá únicamente la nueva columna.



df %>%
  mutate(VarC = VarA/VarB)
## # A tibble: 10 x 4
##    Names     VarA  VarB   VarC
##    <chr>    <dbl> <dbl>  <dbl>
##  1 Spain      120  1250 0.096 
##  2 Italy      110   890 0.124 
##  3 Portugal    80  1550 0.0516
##  4 France     145  2340 0.0620
##  5 Germany    105  3200 0.0328
##  6 Spain      340   530 0.642 
##  7 Italy      345   345 1     
##  8 Portugal   542   321 1.69  
##  9 Spain      237   345 0.687 
## 10 Ireland    543   453 1.20

df %>%
  transmute(VarC = VarA/VarB)
## # A tibble: 10 x 1
##      VarC
##     <dbl>
##  1 0.096 
##  2 0.124 
##  3 0.0516
##  4 0.0620
##  5 0.0328
##  6 0.642 
##  7 1     
##  8 1.69  
##  9 0.687 
## 10 1.20


4.2.1.b. mutate_all(), mutate_if(), mutate_at()


Al igual que hemos visto en otras funciones, la función mutate() tiene también sus respectivas variaciones: mutate_all(), mutate_if() y mutate_at(). Existen numerosos casos en los que estas funciones pueden ser de utilidad. Pongamos que queremos convertir todas las observaciones de todas las columnas a factor, o seleccionar un número determinado de columnas y aplicar logaritmos a todas ellas. Estas operaciones se podrían realizar de la siguiente forma utilizando mutate_all():



df %>%
  mutate_all(as.factor)
## # A tibble: 10 x 3
##    Names    VarA  VarB 
##    <fct>    <fct> <fct>
##  1 Spain    120   1250 
##  2 Italy    110   890  
##  3 Portugal 80    1550 
##  4 France   145   2340 
##  5 Germany  105   3200 
##  6 Spain    340   530  
##  7 Italy    345   345  
##  8 Portugal 542   321  
##  9 Spain    237   345  
## 10 Ireland  543   453

df %>%
  select(2:3) %>%
  mutate_all(log)
## # A tibble: 10 x 2
##     VarA  VarB
##    <dbl> <dbl>
##  1  4.79  7.13
##  2  4.70  6.79
##  3  4.38  7.35
##  4  4.98  7.76
##  5  4.65  8.07
##  6  5.83  6.27
##  7  5.84  5.84
##  8  6.30  5.77
##  9  5.47  5.84
## 10  6.30  6.12


Alternativamente, podríamos indicar que se aplicara logaritmos pero únicamente a las columnas que fuesen de tipo numérico. Incluso podríamos crear una función y aplicarla a dichas columnas. Estas operaciones se podrían realizar con la función mutate_if():



df %>%
  mutate_if(is.numeric, log)
## # A tibble: 10 x 3
##    Names     VarA  VarB
##    <chr>    <dbl> <dbl>
##  1 Spain     4.79  7.13
##  2 Italy     4.70  6.79
##  3 Portugal  4.38  7.35
##  4 France    4.98  7.76
##  5 Germany   4.65  8.07
##  6 Spain     5.83  6.27
##  7 Italy     5.84  5.84
##  8 Portugal  6.30  5.77
##  9 Spain     5.47  5.84
## 10 Ireland   6.30  6.12


# con funcion
divide.1000 <- function(x, na.rm = FALSE) (x/1000)

df %>%
  mutate_if(is.numeric, divide.1000, na.rm = TRUE)
## # A tibble: 10 x 3
##    Names     VarA  VarB
##    <chr>    <dbl> <dbl>
##  1 Spain    0.12  1.25 
##  2 Italy    0.11  0.89 
##  3 Portugal 0.08  1.55 
##  4 France   0.145 2.34 
##  5 Germany  0.105 3.2  
##  6 Spain    0.34  0.53 
##  7 Italy    0.345 0.345
##  8 Portugal 0.542 0.321
##  9 Spain    0.237 0.345
## 10 Ireland  0.543 0.453

 

En un dataframe pequeño como el que estamos utilizando en este post podemos directamente indicar las columnas sobre las que queremos aplicar logaritmos con mutate_at().



df %>%
  mutate_at(c("VarA", "VarB"), log)
## # A tibble: 10 x 3
##    Names     VarA  VarB
##    <chr>    <dbl> <dbl>
##  1 Spain     4.79  7.13
##  2 Italy     4.70  6.79
##  3 Portugal  4.38  7.35
##  4 France    4.98  7.76
##  5 Germany   4.65  8.07
##  6 Spain     5.83  6.27
##  7 Italy     5.84  5.84
##  8 Portugal  6.30  5.77
##  9 Spain     5.47  5.84
## 10 Ireland   6.30  6.12


4.2.2. add_column()


También podemos añadir columnas con la función add_column(). Su funcionamiento es sencillo. Con el siguiente código añadimos una variable nueva (VarC) y una columna titulada Geo. La función select() nos permite ordenar el dataframe a nuestra conveniencia.




df <- df %>%
  add_column(VarC= c(1234, 3200, 5444, 2353, 5675, 3200, 3234, 5632, 1235, 3322)) %>%
  add_column(Geo = c("sur", "sur", "sur", "centro", "norte", "sur", "sur", "sur", "sur", "norte")) %>%
  select(Names, Geo, VarA, VarB, VarC)

datatable(df)


4.2.3. add_count()


La función add_count() añade una nueva columna donde se especifíca en cada fila la suma del número total de observaciones. Por consiguiente, esta cantidad será la misma para todas las observaciones del dataframe. No obstante, también podemos clasificar por alguna variable con el objetivo de que nos indique el número de observaciones que corresponde a cada una de ellas. Como se observa en el ejemplo, esta operación puede ser relevante si la combinamos con otras funciones como filter().



df %>%
  add_count()
## # A tibble: 10 x 6
##    Names    Geo     VarA  VarB  VarC     n
##    <chr>    <chr>  <dbl> <dbl> <dbl> <int>
##  1 Spain    sur      120  1250  1234    10
##  2 Italy    sur      110   890  3200    10
##  3 Portugal sur       80  1550  5444    10
##  4 France   centro   145  2340  2353    10
##  5 Germany  norte    105  3200  5675    10
##  6 Spain    sur      340   530  3200    10
##  7 Italy    sur      345   345  3234    10
##  8 Portugal sur      542   321  5632    10
##  9 Spain    sur      237   345  1235    10
## 10 Ireland  norte    543   453  3322    10

df %>%
  add_count(Geo)
## # A tibble: 10 x 6
##    Names    Geo     VarA  VarB  VarC     n
##    <chr>    <chr>  <dbl> <dbl> <dbl> <int>
##  1 Spain    sur      120  1250  1234     7
##  2 Italy    sur      110   890  3200     7
##  3 Portugal sur       80  1550  5444     7
##  4 France   centro   145  2340  2353     1
##  5 Germany  norte    105  3200  5675     2
##  6 Spain    sur      340   530  3200     7
##  7 Italy    sur      345   345  3234     7
##  8 Portugal sur      542   321  5632     7
##  9 Spain    sur      237   345  1235     7
## 10 Ireland  norte    543   453  3322     2

df %>%
  add_count(Geo) %>%
  filter(n ==1)
## # A tibble: 1 x 6
##   Names  Geo     VarA  VarB  VarC     n
##   <chr>  <chr>  <dbl> <dbl> <dbl> <int>
## 1 France centro   145  2340  2353     1


4.2.3. rename()


La función rename(), como su nombre indica, está diseñada para renombrar las columnas de forma sencilla y rápida.



df %>%
  rename(Country = Names)
## # A tibble: 10 x 5
##    Country  Geo     VarA  VarB  VarC
##    <chr>    <chr>  <dbl> <dbl> <dbl>
##  1 Spain    sur      120  1250  1234
##  2 Italy    sur      110   890  3200
##  3 Portugal sur       80  1550  5444
##  4 France   centro   145  2340  2353
##  5 Germany  norte    105  3200  5675
##  6 Spain    sur      340   530  3200
##  7 Italy    sur      345   345  3234
##  8 Portugal sur      542   321  5632
##  9 Spain    sur      237   345  1235
## 10 Ireland  norte    543   453  3322

df %>%
  rename(Country = Names, Location = Geo)
## # A tibble: 10 x 5
##    Country  Location  VarA  VarB  VarC
##    <chr>    <chr>    <dbl> <dbl> <dbl>
##  1 Spain    sur        120  1250  1234
##  2 Italy    sur        110   890  3200
##  3 Portugal sur         80  1550  5444
##  4 France   centro     145  2340  2353
##  5 Germany  norte      105  3200  5675
##  6 Spain    sur        340   530  3200
##  7 Italy    sur        345   345  3234
##  8 Portugal sur        542   321  5632
##  9 Spain    sur        237   345  1235
## 10 Ireland  norte      543   453  3322