26 de febrero de 2018

Manipulación de Datos con dplyr

El dplyr paquete fue desarrollado por Hadley Wickham de RStudio y es una versión optimizada y destilada de su plyr paquete.

Algunos de los "verbos" clave proporcionados por el dplyr paquete son:

select: devuelve un subconjunto de las columnas de un marco de datos, utilizando una notación flexible

filter: extraer un subconjunto de filas de un marco de datos basado en condiciones lógicas

arrange: reordenar filas de un marco de datos

rename: cambiar el nombre de las variables en un marco de datos

mutate: agregar nuevas variables / columnas o transformar las variables existentes

summarise/ summarize: generar estadísticas de resumen de diferentes variables en el marco de datos, posiblemente dentro de los estratos

%>%: el operador "pipe" se usa para conectar múltiples acciones verbales juntas en una tubería

select

Para los ejemplos, utilizaremos un conjunto de datos que contenga datos sobre la contaminación del aire y la temperatura de la ciudad de Chicago en los Estados Unidos.

chicago <- readRDS("D:/datasets/chicago.rds")

Puede ver algunas características básicas del conjunto de datos con las funciones dim() y str()

dim(chicago)
[1] 6940    8

str(chicago)
'data.frame':   6940 obs. of  8 variables:
 $ city      : chr  "chic" "chic" "chic" "chic" ...
 $ tmpd      : num  31.5 33 33 29 32 40 34.5 29 26.5 32.5 ...
 $ dptp      : num  31.5 29.9 27.4 28.6 28.9 ...
 $ date      : Date, format: "1987-01-01" "1987-01-02" ...
 $ pm25tmean2: num  NA NA NA NA NA NA NA NA NA NA ...
 $ pm10tmean2: num  34 NA 34.2 47 NA ...
 $ o3tmean2  : num  4.25 3.3 3.33 4.38 4.75 ...
 $ no2tmean2 : num  20 23.2 23.8 30.4 30.3 ...

la select() función le permite obtener las pocas columnas que pueda necesitar.

Supongamos que queremos tomar las primeras 3 columnas solamente. Hay algunas maneras de hacer esto. Podríamos, por ejemplo, usar índices numéricos. Pero también podemos usar los nombres directamente.

library(dplyr)
names(chicago)[1:3]
[1] "city" "tmpd" "dptp"
subset <- select(chicago, city:dptp)
head(subset)
  city tmpd   dptp
1 chic 31.5 31.500
2 chic 33.0 29.875
3 chic 33.0 27.375
4 chic 29.0 28.625
5 chic 32.0 28.875
6 chic 40.0 35.125

tenemos en cuenta que : normalmente no puede usarse con nombres o cadenas, pero dentro de select función puede usarse para especificar un rango de nombre de variables.

Tambien puede omitir variables usando la función select usando el signo negativo. Con select puede hacer lo siguiente

#head para mostrar las 6 primeras filas de la selección de variables
head(select(chicago, -(city:dptp)))
        date pm25tmean2 pm10tmean2 o3tmean2 no2tmean2
1 1987-01-01         NA   34.00000 4.250000  19.98810
2 1987-01-02         NA         NA 3.304348  23.19099
3 1987-01-03         NA   34.16667 3.333333  23.81548
4 1987-01-04         NA   47.00000 4.375000  30.43452
5 1987-01-05         NA         NA 4.750000  30.33333
6 1987-01-06         NA   48.00000 5.833333  25.77233

lo que indica la linea de comandos es que debemos incluir todas las variables excepto city hasta dptp, las variables city tmpd dptp

La función select también permite usar una sintaxis especial que permite especificar nombres de variables basado en patrones por ejemplo, si quisieramos selecionar aquellas variables que terminen con un 2, podríamos hacer lo siguiente

subset <- select(chicago, ends_with("2"))
str(subset)
'data.frame':   6940 obs. of  4 variables:
 $ pm25tmean2: num  NA NA NA NA NA NA NA NA NA NA ...
 $ pm10tmean2: num  34 NA 34.2 47 NA ...
 $ o3tmean2  : num  4.25 3.3 3.33 4.38 4.75 ...
 $ no2tmean2 : num  20 23.2 23.8 30.4 30.3 ...

o si quisíeramos selecionar aquellas variables que comience con la letra "d", podríamos hacer lo siguiente

subset <- select(chicago, starts_with("d"))
str(subset)
'data.frame':   6940 obs. of  2 variables:
 $ dptp: num  31.5 29.9 27.4 28.6 28.9 ...
 $ date: Date, format: "1987-01-01" "1987-01-02" ...

filter()

La función filter se usa para extraer subconjuntos de filas de un marco de datos. Esta función es similar a la función subset() existente en R que es bastante más rápida.

Supongamos que queremos extraer las filas del dataset chicago donde los niveles PM25tmean2 son mayores a 30, podríamos hacer lo siguiente

chic.f <- filter(chicago, pm25tmean2 > 30)
str(chic.f)
'data.frame':   194 obs. of  8 variables:
 $ city      : chr  "chic" "chic" "chic" "chic" ...
 $ tmpd      : num  23 28 55 59 57 57 75 61 73 78 ...
 $ dptp      : num  21.9 25.8 51.3 53.7 52 56 65.8 59 60.3 67.1 ...
 $ date      : Date, format: "1998-01-17" "1998-01-23" ...
 $ pm25tmean2: num  38.1 34 39.4 35.4 33.3 ...
 $ pm10tmean2: num  32.5 38.7 34 28.5 35 ...
 $ o3tmean2  : num  3.18 1.75 10.79 14.3 20.66 ...
 $ no2tmean2 : num  25.3 29.4 25.3 31.4 26.8 ...

podemos observar que ahora solo hay 194 filas en el marco de datos y la distribución de los valores pm25tmean2 es

summary(chic.f$pm25tmean2)
   Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
  30.05   32.12   35.04   36.63   39.53   61.50 

tambien podríamos colocar una secuancia lógica arbitrariamente compleja dentro de filter , por lo que podríamos, por ejemplo, extraer las filas donde PM25tmean2 es mayor a 30 y la temperatura = tmpd es mayor a 80 grados Fahrenheit

chic.f <- filter(chicago, pm25tmean2 > 30 & tmpd > 80)
select(chic.f, date, tmpd, pm25tmean2)
         date tmpd pm25tmean2
1  1998-08-23   81   39.60000
2  1998-09-06   81   31.50000
3  2001-07-20   82   32.30000
4  2001-08-01   84   43.70000
5  2001-08-08   85   38.83750
6  2001-08-09   84   38.20000
7  2002-06-20   82   33.00000
8  2002-06-23   82   42.50000
9  2002-07-08   81   33.10000
10 2002-07-18   82   38.85000
11 2003-06-25   82   33.90000
12 2003-07-04   84   32.90000
13 2005-06-24   86   31.85714
14 2005-06-27   82   51.53750
15 2005-06-28   85   31.20000
16 2005-07-17   84   32.70000
17 2005-08-03   84   37.90000

arrange

La arrange función se usa para reordenar las filas de un marco de datos de acuerdo con una de las variables / columnas.

Aquí podemos ordenar las filas del marco de datos por fecha, de modo que la primera fila sea la observación más antigua y la última sea la observación más reciente.

chicago <- arrange(chicago, date)
head(select(chicago, date, pm25tmean2))
        date pm25tmean2
1 1987-01-01         NA
2 1987-01-02         NA
3 1987-01-03         NA
4 1987-01-04         NA
5 1987-01-05         NA
6 1987-01-06         NA

tail(select(chicago, date, pm25tmean2))
           date pm25tmean2
6935 2005-12-26    8.40000
6936 2005-12-27   23.56000
6937 2005-12-28   17.75000
6938 2005-12-29    7.45000
6939 2005-12-30   15.05714
6940 2005-12-31   15.00000

Las columnas también pueden organizarse en orden descendente utilizando eloperador desc()

chicago <- arrange(chicago, desc(date))

head(select(chicago, date, pm25tmean2))
        date pm25tmean2
1 2005-12-31   15.00000
2 2005-12-30   15.05714
3 2005-12-29    7.45000
4 2005-12-28   17.75000
5 2005-12-27   23.56000
6 2005-12-26    8.40000
tail(select(chicago, date, pm25tmean2))
           date pm25tmean2
6935 1987-01-06         NA
6936 1987-01-05         NA
6937 1987-01-04         NA
6938 1987-01-03         NA
6939 1987-01-02         NA
6940 1987-01-01         NA

Al observar las tres primeras y las últimas tres filas, se muestran las fechas en orden descendente.

rename

Renombrar una variable en un marco de datos en R es sorprendentemente difícil de hacer. La función rename() está diseñada para facilitar este proceso.

#mostramos las cinco primeras variables del dataset chicago
head(chicago[, 1:5])
  city tmpd dptp       date pm25tmean2
1 chic   35 30.1 2005-12-31   15.00000
2 chic   36 31.0 2005-12-30   15.05714
3 chic   35 29.4 2005-12-29    7.45000
4 chic   37 34.5 2005-12-28   17.75000
5 chic   40 33.6 2005-12-27   23.56000
6 chic   35 29.6 2005-12-26    8.40000

podemos renombrar las variables dptp = temperatura y pm25tmean2 = pm25

chicago <- rename(chicago, temperatura = dptp, pm25 = pm25tmean2)
head(chicago[, 1:5])
  city tmpd temperatura       date     pm25
1 chic   35        30.1 2005-12-31 15.00000
2 chic   36        31.0 2005-12-30 15.05714
3 chic   35        29.4 2005-12-29  7.45000
4 chic   37        34.5 2005-12-28 17.75000
5 chic   40        33.6 2005-12-27 23.56000
6 chic   35        29.6 2005-12-26  8.40000

mutate

La función mutate existe para calcular transformaciones de variables en un marco de datos. A menudo, desea crear nuevas variables derivadas de variables existentes y mutate() proporciona una interfaz limpia para hacerlo.

Por ejemplo, con los datos de contaminación del aire, a menudo queremos degenerar los datos al restar la media de los datos.

chicago <- mutate(chicago, mp25detrend = pm25 - mean(pm25, na.rm = TRUE))
head(chicago)
  city tmpd temperatura       date     pm25 pm10tmean2  o3tmean2 no2tmean2
1 chic   35        30.1 2005-12-31 15.00000       23.5  2.531250  13.25000
2 chic   36        31.0 2005-12-30 15.05714       19.2  3.034420  22.80556
3 chic   35        29.4 2005-12-29  7.45000       23.5  6.794837  19.97222
4 chic   37        34.5 2005-12-28 17.75000       27.5  3.260417  19.28563
5 chic   40        33.6 2005-12-27 23.56000       27.0  4.468750  23.50000
6 chic   35        29.6 2005-12-26  8.40000        8.5 14.041667  16.81944
  mp25detrend
1   -1.230958
2   -1.173815
3   -8.780958
4    1.519042
5    7.329042
6   -7.830958

Gráficos Exploratorio

class <- c("numeric", "character", "factor", "numeric", "numeric")
pollution <- read.csv("D:/datasets/avgpm25.csv", colClasses = class)
head(pollution)
       pm25  fips region longitude latitude
1  9.771185 01003   east -87.74826 30.59278
2  9.993817 01027   east -85.84286 33.26581
3 10.688618 01033   east -87.72596 34.73148
4 11.337424 01049   east -85.79892 34.45913
5 12.119764 01055   east -86.03212 34.01860
6 10.827805 01069   east -85.35039 31.18973

Diagrama de caja

boxplot(pollution$pm25, col = "red")

library(maps)
map("county", "california")
with(filter(pollution, pm25 > 15), points(longitude, latitude))

Histograma

hist(pollution$pm25, col = "green")

Barplot

library(dplyr)
table(pollution$region) %>% 
  barplot(col = "wheat")

Múltiples diagramas de caja

boxplot(pm25 ~ region, data = pollution, col = "red")

Diagramas de dispersión

with(pollution, plot(latitude, pm25))
abline(h = 12, lwd = 2, lty = 2)

Scatterplot: uso del color

with(pollution, plot(latitude, pm25, col = region))
abline(h = 12, lwd = 2, lty = 2)

Múltiples diagramas de dispersión

par(mfrow = c(1, 2), mar = c(5, 4, 2, 1))
with(subset(pollution, region == "west"), plot(latitude, pm25, main = "West"))
with(subset(pollution, region == "east"), plot(latitude, pm25, main = "East"))