¿Qué vamos a aprender?

En esta clase vamos a aprender a usar algunos paquetes para limpiar datos y estructurar información en R. En las clases anteriores vimos algunas características que deben tener los datos limpios:

  1. Cada columna es una variable: una variable contiene todos los valores que miden el atributo (altura, peso, temperatura, etc)
  2. Cada fila es una observación

¿Qué paquetes vamos a necesitar?

library(dplyr)
library(tidyr) 
library(readxl)

Importar los datos

Antes de comenzar, hay que cambiar el directorio de trabajo y seleccionar el folder en donde tenemos nuestros archivos. Esto se hace con el comando setwd().

Ahora podemos importar los archivos de varias formas. Podemos hacerlo desde el menú de arriba, usando: File -> Import Dataset y seleccionando el tipo de archivo que queremos importar.

También podemos hacerlo escribiendo el código. Es siempre recomendable asignar el archivo que importamos a un objeto con el símbolo <-. Inicialmente vamos a importar unos archivos .xlsx, por lo que usamos el paquete readxl, que ya instalamos.

Los archivos que vamos a usar inicialmente son:

#Recuerden cambiar el directorio de trabajo
setwd("/Users/Camila/Documents/Curso periodismo datos/2017/Clases/Limpieza_R")
morosidad16 <- read_xlsx("morosidad16.xlsx")
morosidad17<- read_xlsx("morosidad17.xlsx")

Explorar los datos y unir las bases

Antes de comenzar a limpiar o analizar los datos tenemos que explorar los datos. Para estos primeros ejercicios vamos a usar las bases de datos de morosidad con la CCSS.

Ambas bases de datos tienen las siguientes variables:

Cómo primer paso vamos a unir ambas bases de datos.

Unir bases de datos

Para unir bases de datos necesitamos una o más variables en común entre las dos bases de datos. Existen varias funciones para unir bases de datos. Una de ellas es merge, que sirve para unir columnas de dos bases de datos diferentes. Para unir bases es clave hacerse la pregunta: ¿Queremos conservar todas las variables o solo las que hacen match?. De acuerdo a la respuesta, así va a depender la fórmula que usemos.

La sintaxis de merge() es simple:
merge(base1, base2, by.x="nombre variable base 1", by.y="nombre variable base 2")

En el caso en el que la variable se llame igual en las dos bases: merge(base1, base2, by="nombre variable")

En esos ejemplos, el comando une solamente los casos en común entre las dos bases.

Si queremos que se unan todos los casos, usamos la opción all=TRUE: merge(base1, base2, by="nombre variable", all=TRUE)

Pueden ver este documento donde se muestra cómo funciona esta función con detalle. link

Para este ejercicio queremos unir las dos bases de morosidad en una sola, dejando todas las observaciones de ambas bases, entonces usamos el comando:

morosidad<-merge(morosidad17, morosidad16, by= "id", all=TRUE)

Ahora podemos convertirla base a una tibble para facilitar la lectura

morosidad <-tbl_df(morosidad)

Explorar los datos

Ahora que tenemos una nueva base de datos, podemos explorar sus contenidos. Usemos las siguientes funciones:

Si queremos imprimir la base de datos, nada más ponemos el nombre del objeto:

morosidad
## # A tibble: 78,703 x 10
##         id                                  nombre.x deuda17
##      <dbl>                                     <chr>   <dbl>
##  1       0                     VAN ADELBERGEN ISOLDA  265838
##  2   15452                  BLAISE BLAISE CHRISTOPHE   83414
##  3   34382 INDUSTRIAS ELECTRONICAS COSTARRICENSES SA    7808
##  4   47329                 VANNUCCI VANNUCCI ALBERTO  620534
##  5   50075   MARIA SELENIA CAYETANA CARVAJAL VENEGAS  506818
##  6  149005       ROSARIO CONEJO FÑCRUZ MARY GUASCH C    8240
##  7  469611               SAM SAM BRIAN WALTER HUBERT  526936
##  8  611086                 MULLER MULLER JEAN-CLAUDE  103397
##  9  776002         RODRIGUEZ RODRIGUEZ VICTOR MANUEL   63089
## 10 1070043                    MARKS RUIZ HENRY JAMES 1451873
## # ... with 78,693 more rows, and 7 more variables: situacion.x <chr>,
## #   lugar.pago.x <chr>, Estado <chr>, nombre.y <chr>, deuda16 <dbl>,
## #   situacion.y <chr>, lugar.pago.y <chr>

dim() Esta función nos permite ver la dimensión de la base de datos, en este caso tenemos 10 variables y 78.703 observaciones

dim(morosidad)
## [1] 78703    10

head() Nos permite ver las primeras filas de la base de datos. Incluso podemos seleccionar la cantidad de filas que queremos ver por ejemplo head(base, n=20), lo cual nos muestra las primeras 20 filas. También podemos ver que nos muestra el tipo de variable.

head(morosidad)
## # A tibble: 6 x 10
##       id                                  nombre.x deuda17
##    <dbl>                                     <chr>   <dbl>
## 1      0                     VAN ADELBERGEN ISOLDA  265838
## 2  15452                  BLAISE BLAISE CHRISTOPHE   83414
## 3  34382 INDUSTRIAS ELECTRONICAS COSTARRICENSES SA    7808
## 4  47329                 VANNUCCI VANNUCCI ALBERTO  620534
## 5  50075   MARIA SELENIA CAYETANA CARVAJAL VENEGAS  506818
## 6 149005       ROSARIO CONEJO FÑCRUZ MARY GUASCH C    8240
## # ... with 7 more variables: situacion.x <chr>, lugar.pago.x <chr>,
## #   Estado <chr>, nombre.y <chr>, deuda16 <dbl>, situacion.y <chr>,
## #   lugar.pago.y <chr>

tail() Nos permite ver las últimas filas. Tiene la misma sintaxis que head()

tail(morosidad)
## # A tibble: 6 x 10
##            id                                      nombre.x deuda17
##         <dbl>                                         <chr>   <dbl>
## 1 14400964459               PAUL ROBERT OKEEFE NOINDICAOTRO 6838595
## 2 14528400520                    INDUSTRIAS DON RICHARD S A  429487
## 3 18400600004                    FERRETERIA EL PROGRESO S A  206436
## 4 31010287878 SOLUCIONES MODERNAS Y DE SEGURIDAD SOMOS S.A.  255875
## 5 31011413537                                          <NA>      NA
## 6 31021120501                 SUPER MERCADO EL KACIQUE LTDA  875409
## # ... with 7 more variables: situacion.x <chr>, lugar.pago.x <chr>,
## #   Estado <chr>, nombre.y <chr>, deuda16 <dbl>, situacion.y <chr>,
## #   lugar.pago.y <chr>

glimpse() nos permite exploarar las variables. Nos dice, al lado de cada variable cuál es el tipo. Por ejemplo nos dice que nombre.x es caracter y que deuda17 es “double”, el cual es un formato numérico.

glimpse(morosidad)
## Observations: 78,703
## Variables: 10
## $ id           <dbl> 0, 15452, 34382, 47329, 50075, 149005, 469611, 61...
## $ nombre.x     <chr> "VAN ADELBERGEN ISOLDA", "BLAISE BLAISE CHRISTOPH...
## $ deuda17      <dbl> 265838, 83414, 7808, 620534, 506818, 8240, 526936...
## $ situacion.x  <chr> "DIFICIL COBRO", "COBRO ADMINISTRATIVO", "COBRO A...
## $ lugar.pago.x <chr> "SUCURSAL DESAMPARADOS", "SUCURSAL SANTA CRUZ", "...
## $ Estado       <chr> "Inactivo", "Inactivo", "Inactivo", "Inactivo", "...
## $ nombre.y     <chr> "VAN  ADELBERGEN ISOLDA", "BLAISE BLAISE CHRISTOP...
## $ deuda16      <dbl> 133761, 42569, 4000, 313886, NA, NA, 264303, 5254...
## $ situacion.y  <chr> "COBRO ADMINISTRATIVO", "COBRO ADMINISTRATIVO", "...
## $ lugar.pago.y <chr> "SUCURSAL DESAMPARADOS", "SUCURSAL SANTA CRUZ", "...

dplyr

Uno de los paquetes que más funciona para manipular datos de forma fácil es dplyr. Este paquete tiene, entre otras, cinco funciones para manipular datos: select() filter() arrange()``mutate() summarize().

Veámos cómo se usa

select()

Select nos permite seleccionar columnas. La sintaxis sería: select(dataframe, col1, col2) conde col1, col2, se refiere a los nombres de las columnas que queramos seleccionar.

Por ejemplo supongamos que queremos seleccionar únicamente las columnas de id y deuda:

select(morosidad, id, deuda17, deuda16)
## # A tibble: 78,703 x 3
##         id deuda17 deuda16
##      <dbl>   <dbl>   <dbl>
##  1       0  265838  133761
##  2   15452   83414   42569
##  3   34382    7808    4000
##  4   47329  620534  313886
##  5   50075  506818      NA
##  6  149005    8240      NA
##  7  469611  526936  264303
##  8  611086  103397   52546
##  9  776002   63089      NA
## 10 1070043 1451873  799625
## # ... with 78,693 more rows

También podemos seleccionar todas las columnas menos algunas, esto lo hacemos poniendo - antes del nombre de la columna que no queremos seleccionar. Por ejemplo, si queremos todas las columnas menos Estado:

select(morosidad, -Estado)
## # A tibble: 78,703 x 9
##         id                                  nombre.x deuda17
##      <dbl>                                     <chr>   <dbl>
##  1       0                     VAN ADELBERGEN ISOLDA  265838
##  2   15452                  BLAISE BLAISE CHRISTOPHE   83414
##  3   34382 INDUSTRIAS ELECTRONICAS COSTARRICENSES SA    7808
##  4   47329                 VANNUCCI VANNUCCI ALBERTO  620534
##  5   50075   MARIA SELENIA CAYETANA CARVAJAL VENEGAS  506818
##  6  149005       ROSARIO CONEJO FÑCRUZ MARY GUASCH C    8240
##  7  469611               SAM SAM BRIAN WALTER HUBERT  526936
##  8  611086                 MULLER MULLER JEAN-CLAUDE  103397
##  9  776002         RODRIGUEZ RODRIGUEZ VICTOR MANUEL   63089
## 10 1070043                    MARKS RUIZ HENRY JAMES 1451873
## # ... with 78,693 more rows, and 6 more variables: situacion.x <chr>,
## #   lugar.pago.x <chr>, nombre.y <chr>, deuda16 <dbl>, situacion.y <chr>,
## #   lugar.pago.y <chr>

Si queremos seleccionar un rango de columnas por ejemplo de id a situacion usamos :.

select(morosidad, id:situacion.x)
## # A tibble: 78,703 x 4
##         id                                  nombre.x deuda17
##      <dbl>                                     <chr>   <dbl>
##  1       0                     VAN ADELBERGEN ISOLDA  265838
##  2   15452                  BLAISE BLAISE CHRISTOPHE   83414
##  3   34382 INDUSTRIAS ELECTRONICAS COSTARRICENSES SA    7808
##  4   47329                 VANNUCCI VANNUCCI ALBERTO  620534
##  5   50075   MARIA SELENIA CAYETANA CARVAJAL VENEGAS  506818
##  6  149005       ROSARIO CONEJO FÑCRUZ MARY GUASCH C    8240
##  7  469611               SAM SAM BRIAN WALTER HUBERT  526936
##  8  611086                 MULLER MULLER JEAN-CLAUDE  103397
##  9  776002         RODRIGUEZ RODRIGUEZ VICTOR MANUEL   63089
## 10 1070043                    MARKS RUIZ HENRY JAMES 1451873
## # ... with 78,693 more rows, and 1 more variables: situacion.x <chr>

Si queremos guardar el resultado de esa función en un nuevo objeto, debemos asignarlo con <-. Por ejemplo para este ejericio nos interesa quedarnos únicamente con columnas que no estén repetidas. Si observamos la base, nos damos cuenta que la columna de nombre, lugar de pago y situación se repiten, entonces vamos a deseleccionar esas columnas y crear un nuevo objeto que se llame morosidad1.

morosidad1 <- select(morosidad, -nombre.y, -situacion.y, -lugar.pago.y)
morosidad1
## # A tibble: 78,703 x 7
##         id                                  nombre.x deuda17
##      <dbl>                                     <chr>   <dbl>
##  1       0                     VAN ADELBERGEN ISOLDA  265838
##  2   15452                  BLAISE BLAISE CHRISTOPHE   83414
##  3   34382 INDUSTRIAS ELECTRONICAS COSTARRICENSES SA    7808
##  4   47329                 VANNUCCI VANNUCCI ALBERTO  620534
##  5   50075   MARIA SELENIA CAYETANA CARVAJAL VENEGAS  506818
##  6  149005       ROSARIO CONEJO FÑCRUZ MARY GUASCH C    8240
##  7  469611               SAM SAM BRIAN WALTER HUBERT  526936
##  8  611086                 MULLER MULLER JEAN-CLAUDE  103397
##  9  776002         RODRIGUEZ RODRIGUEZ VICTOR MANUEL   63089
## 10 1070043                    MARKS RUIZ HENRY JAMES 1451873
## # ... with 78,693 more rows, and 4 more variables: situacion.x <chr>,
## #   lugar.pago.x <chr>, Estado <chr>, deuda16 <dbl>

filter()

La función filter nos permite filtrar filas.

La sintaxis es simple: filter(base, condicion). Donde condición es la condión lógica por la que queremos filtrar datos. Para ello usamos operadores lógicos:

  • >: mayor que
  • <: menor que
  • >=: mayor o igual que
  • <=: menor o igual que
  • ==: igual que (se ponen dos signos de igual)
  • !=: diferente
  • &: y
  • |: o
  • is.na(variable): filtra los valores en blanco de la variable seleccionada.
  • !is.na(variable): filtra los valores que no están en blanco de la variable.

Por ejemplo si queremos filtrar solamente las deudas superiores a un millón:

filter(morosidad1, deuda17>1000000)
## # A tibble: 30,438 x 7
##          id                       nombre.x  deuda17          situacion.x
##       <dbl>                          <chr>    <dbl>                <chr>
##  1  1070043         MARKS RUIZ HENRY JAMES  1451873       COBRO JUDICIAL
##  2  3000465 HERNANDEZ RODAS MANUEL ANTONIO  2156724 COBRO ADMINISTRATIVO
##  3  4968006 SUCES DE EDUARDO ROJAS QUESADA 17668269 COBRO ADMINISTRATIVO
##  4  9700486       VERONICA ALVAREZ ZAMORAN  4177836 COBRO ADMINISTRATIVO
##  5 10000000        ANIBAL HERRERA BAUDELIO  1332517 COBRO ADMINISTRATIVO
##  6 11003242               RINE BORBON LUIS  1771856       COBRO JUDICIAL
##  7 11703874 MOSSUTO FONTANA ROCCO GIUSEPPE  1866968       COBRO JUDICIAL
##  8 11851989        PETER ALEXANDER TEODORI  1284362       COBRO JUDICIAL
##  9 11852243               DAMIA DAMIA EMIL  4685940 COBRO ADMINISTRATIVO
## 10 11880274    SCHLICKER SCHINDLBECK FRANK  1293144        DIFICIL COBRO
## # ... with 30,428 more rows, and 3 more variables: lugar.pago.x <chr>,
## #   Estado <chr>, deuda16 <dbl>

O las deudas que crecieron entre 2016 y 2017:

filter(morosidad1, deuda17>deuda16)
## # A tibble: 56,539 x 7
##         id                                  nombre.x deuda17
##      <dbl>                                     <chr>   <dbl>
##  1       0                     VAN ADELBERGEN ISOLDA  265838
##  2   15452                  BLAISE BLAISE CHRISTOPHE   83414
##  3   34382 INDUSTRIAS ELECTRONICAS COSTARRICENSES SA    7808
##  4   47329                 VANNUCCI VANNUCCI ALBERTO  620534
##  5  469611               SAM SAM BRIAN WALTER HUBERT  526936
##  6  611086                 MULLER MULLER JEAN-CLAUDE  103397
##  7 1070043                    MARKS RUIZ HENRY JAMES 1451873
##  8 2380627                     PLATERO FRANCO MARVIN  717483
##  9 3000465            HERNANDEZ RODAS MANUEL ANTONIO 2156724
## 10 9700486                  VERONICA ALVAREZ ZAMORAN 4177836
## # ... with 56,529 more rows, and 4 more variables: situacion.x <chr>,
## #   lugar.pago.x <chr>, Estado <chr>, deuda16 <dbl>

O solamente las deudas mayores a un millón y de díficil cobro:

filter(morosidad1, deuda17>1000000 & situacion.x=="DIFICIL COBRO")
## # A tibble: 9,482 x 7
##          id                        nombre.x  deuda17   situacion.x
##       <dbl>                           <chr>    <dbl>         <chr>
##  1 11880274     SCHLICKER SCHINDLBECK FRANK  1293144 DIFICIL COBRO
##  2 12050037               DIAZ PILOTO JUSTO 22229809 DIFICIL COBRO
##  3 12251917              BIRD BIRD GEOFFREY  1267763 DIFICIL COBRO
##  4 13307917       LEWKOWICZ LEWKOWICZ HENRY  2074144 DIFICIL COBRO
##  5 13454769 BUSTOS VALDERRAMA JULIO ALBERTO  3317977 DIFICIL COBRO
##  6 13480637           PEREZ GIMENEZ VICENTE  1830254 DIFICIL COBRO
##  7 13509132      SEIDLER SEIDLER KARL PETER  4838378 DIFICIL COBRO
##  8 13952420     WILKIN WILKIN JEREMY ROBERT  1188119 DIFICIL COBRO
##  9 14050168            JANDREZ LOPEZ OVIDIO  4053836 DIFICIL COBRO
## 10 14110905   CETROLA CETROLA JULIO DOMINGO  1072692 DIFICIL COBRO
## # ... with 9,472 more rows, and 3 more variables: lugar.pago.x <chr>,
## #   Estado <chr>, deuda16 <dbl>

En este ejemplo, tenemos deudas del 2016 y del 2017, y nos interesa analizar únicamente los casos de las empresas o personas que han estado morosas por los dos años. Para ello podemos usar la función filter:

morosidad1 <- filter(morosidad1, !is.na(deuda17), !is.na(deuda16))

El código de arriba lo que hace es filtrar la base por todos aquellos registros que no tengan valores vacíos en 2017 y luego por todos los que no tienen registros vacíos en 2016. Como podemos ver, esto nos da como resultado menos registros en nuestra base de datos.

mutate()

Mutate nos permite crear nuevas columnas de forma fácil.

Podemos crear una variable que me diga cuánto cambió la deuda, que es la diferencia entre deuda17 y deuda16:

morosidad1 <- mutate(morosidad1, cambio.deuda=deuda17-deuda16)

Ahora podemos crear una nueva variable que me categorice el cambio en la deuda en si aumentó o no. Esto podemos hacerlo con la función if_else() o ifelse (funcionar igual). La sintaxis es: ifelse(condición, valor cierto, valor falso). (Es similar a la función if en Excel).

morosidad1 <- mutate(morosidad1, tipo.cambio=ifelse(cambio.deuda<0,"disminuyó", "aumentó"))

Con mutate podemos crear multiples variables a la vez, separando cada una por coma, por ejemplo:

morosidad1 <- mutate(morosidad1, cambio.deuda=deuda17-deuda16,
                     tipo.cambio=ifelse(cambio.deuda<0,"disminuyó", "aumentó"))

arrange()

Arrange nos permite ordenar las base por una o varias columnas

Por ejemplo, queremos ordenar la base en orden ascendente por deuda17 y por cambio.deuda:

morosidad1 <- arrange(morosidad1, deuda17, cambio.deuda)

Si lo queremos en orden descendente usamos desc()

morosidad1 <- arrange(morosidad1, desc(deuda17), desc(cambio.deuda))

Simplificar el trabajo: %>%

Un operador muy útil cuando trabajamos con dplyr es pipe operator que visualmente se ve así %>%. Este operador nos va a facilitar muchísimo el trabajo con funciones y nos permite hacer comando con menos líneas de código.

¿Cómo funciona el %>%? Lo primero es poner el ibjeto (tabla o dataframe) al cual queremos aplicar las operaciones de la forma base %>% funcion(). Esto nos ahorra estar poniendo como primer argumento de las funciones de dplyr al objeto.

Por ejemplo, recapitulemos todas las líneas de código que usamos anteriormente para limpiar la base de datos:

morosidad1 <- select(morosidad, -nombre.y, -situacion.y, -lugar.pago.y)
morosidad1 <- filter(morosidad1, !is.na(deuda17), !is.na(deuda16))
morosidad1 <- mutate(morosidad1, cambio.deuda=deuda17-deuda16)
morosidad1 <- mutate(morosidad1, tipo.cambio=ifelse(cambio.deuda<0,"disminuyó", "aumentó"))
morosidad1 <- arrange(morosidad1, desc(deuda17), desc(cambio.deuda))

Todos los pasos realizados anteriormente podríamos haberlos hecho de forma más simple usando el %>%:

morosidad2 <- morosidad %>%
  select(-nombre.y, -situacion.y, -lugar.pago.y) %>%
  filter(!is.na(deuda17), !is.na(deuda16)) %>%
  mutate(cambio.deuda=deuda17-deuda16,
       tipo.cambio=ifelse(cambio.deuda<0,"disminuyó", "aumentó")) %>%
  arrange(desc(deuda17), desc(cambio.deuda))

Exportar base limpia a otros formatos

Ahora que tenemos la base limpia podemos exportarla a otros formatos por ejemplo a csv.

write.csv(morosidad2, "baselimpia.csv")

tidyr

tidyr es un paquete diseñado para tener datos ¨tidy¨ o limpios. Esos datos siguen dos principios que ya hemos visto reiteradamente: Cada variable está en una sola columna y cada fila es una observación.

Para entender mejor qué es “tidy data”, puede leer este artículo: Tidy data - Hadley Wickham

Este paquete tiene 4 funciones principales gather() spread() separate() y unite().

Antes de comenzar a ver las funciones importemos los archivos de trabajo:

#Ponemos tbl_df() para convertirlo de una vez a una tibble
estudiantes <- tbl_df(read.csv("students.csv", header = T, sep= ","))
estudiantes2<- tbl_df(read.csv("students2.csv", header = T, sep= ","))

Veamos estudiantes:

estudiantes
## # A tibble: 5 x 3
##    grade  male female
##   <fctr> <int>  <int>
## 1      A     1      5
## 2      B     5      0
## 3      C     5      2
## 4      D     5      5
## 5      E     7      4

¿Cuál es el problema? male y female son valores de la variable sexo, por lo que hay que cambiar la estructura de la base de datos. Esta estructura de una base de datos se conoce como “formato ancho” y tenemos que convertirla a un “formato largo”. Para eso usamos la función gather().

gather()

La función toma las columnas múltiples, las colapsa en una sola y crea una nueva columna con los valores respectivos.

La sintaxis es gather(data, key, value, columnas) o data %>% gather(key, value, columnas). Donde:

  • data: es la tabla o el data frame
  • key: es el nombre que le voy a dar a la variable que voy a “fundir”.
  • value: nombre de la variable que va a guardar los valores.
  • columna: las columnas que quiero fundir. Podemos ponerlas separadas por coma, o pondemos usar el operador - para seleccionar todas las columnas menos una.

En este ejemplo para reestructurar estudiantes el comando sería:

estudiantes_long <- gather(estudiantes, sexo, frecuencia, -grade)
estudiantes_long
## # A tibble: 10 x 3
##     grade   sexo frecuencia
##    <fctr>  <chr>      <int>
##  1      A   male          1
##  2      B   male          5
##  3      C   male          5
##  4      D   male          5
##  5      E   male          7
##  6      A female          5
##  7      B female          0
##  8      C female          2
##  9      D female          5
## 10      E female          4

spread()

Es la función contraria a gather(), que nos devolvería a la tabla original

estudiantes_wide <- spread(estudiantes_long, sexo, frecuencia)
estudiantes_wide
## # A tibble: 5 x 3
##    grade female  male
## * <fctr>  <int> <int>
## 1      A      5     1
## 2      B      0     5
## 3      C      2     5
## 4      D      5     5
## 5      E      4     7

Veamos ahora qué pasa con estudiantes2:

estudiantes2
## # A tibble: 5 x 5
##    grade male_1 female_1 male_2 female_2
##   <fctr>  <int>    <int>  <int>    <int>
## 1      A      3        4      3        4
## 2      B      6        4      3        5
## 3      C      7        4      3        8
## 4      D      4        0      8        1
## 5      E      1        1      2        7

En este caso tenemos un doble problema tenemos valores de una misma variable en diferentes columnas y diferentes variables en una sola. En este caso nos separa a los hombres y mujeres segun la clase en la que están: 1 y 2.

Entonces tenemos que hacer dos pasos. Primero usamos la función gather():

estudiantes2_long <- gather(estudiantes2, sexo_clase, frecuencia, -grade)
estudiantes2_long
## # A tibble: 20 x 3
##     grade sexo_clase frecuencia
##    <fctr>      <chr>      <int>
##  1      A     male_1          3
##  2      B     male_1          6
##  3      C     male_1          7
##  4      D     male_1          4
##  5      E     male_1          1
##  6      A   female_1          4
##  7      B   female_1          4
##  8      C   female_1          4
##  9      D   female_1          0
## 10      E   female_1          1
## 11      A     male_2          3
## 12      B     male_2          3
## 13      C     male_2          3
## 14      D     male_2          8
## 15      E     male_2          2
## 16      A   female_2          4
## 17      B   female_2          5
## 18      C   female_2          8
## 19      D   female_2          1
## 20      E   female_2          7

Y ahora usamos la función separate().

separate()

Esta función nos permite separar columnas. La sintaxis es:

separate(data, col, into, sep), donde:

  • data: es la tabla o el data frame
  • col: la columna que hay que separar
  • into: las columnas por las que vamos a separar. Se pueden poner como vector de la forma c(“col1”, “col2”)
  • sep: separador, por ejemplo comas, puntos, guion bajo u otros caracteres. Si no se especifica el argumento R trata de identificar el patrón para separar los datos. Cuando se utiliza esta opción se debe poner sep=" " (entre comillas iría el caracter que usemos para separar)

En este ejemplo, queremos separar el sexo de la clase.

estudiantes2_long2 <- separate(estudiantes2_long, sexo_clase, c("sexo", "clase"))
#En este caso R detectó el caracter para separar, el resultado es igual a si hubiéramos puesto la opción sep="_"
estudiantes2_long2
## # A tibble: 20 x 4
##     grade   sexo clase frecuencia
##  * <fctr>  <chr> <chr>      <int>
##  1      A   male     1          3
##  2      B   male     1          6
##  3      C   male     1          7
##  4      D   male     1          4
##  5      E   male     1          1
##  6      A female     1          4
##  7      B female     1          4
##  8      C female     1          4
##  9      D female     1          0
## 10      E female     1          1
## 11      A   male     2          3
## 12      B   male     2          3
## 13      C   male     2          3
## 14      D   male     2          8
## 15      E   male     2          2
## 16      A female     2          4
## 17      B female     2          5
## 18      C female     2          8
## 19      D female     2          1
## 20      E female     2          7

Estos pasos podemos simplificarlos en uno solo con el uso del %>%:

estudiantes2_long <- estudiantes2 %>%
  gather(sexo_clase, frecuencia, -grade) %>%
  separate(sexo_clase, c("sexo", "clase"))  %>%
  print
## # A tibble: 20 x 4
##     grade   sexo clase frecuencia
##  * <fctr>  <chr> <chr>      <int>
##  1      A   male     1          3
##  2      B   male     1          6
##  3      C   male     1          7
##  4      D   male     1          4
##  5      E   male     1          1
##  6      A female     1          4
##  7      B female     1          4
##  8      C female     1          4
##  9      D female     1          0
## 10      E female     1          1
## 11      A   male     2          3
## 12      B   male     2          3
## 13      C   male     2          3
## 14      D   male     2          8
## 15      E   male     2          2
## 16      A female     2          4
## 17      B female     2          5
## 18      C female     2          8
## 19      D female     2          1
## 20      E female     2          7
#el comando print, nos imprime el resultado

unite()

Es el contrario a separate. unite(data, col, ... , sep), donde:

  • data: es la tabla o el data frame
  • col: la nueva columna con los valores unidos
  • ...: la lista de columnas que queremos unir
  • sep: separador que va a unir las columnas, por ejemplo _.

En este caso si queremos volver a la tabla original:

estudiantes2_unida <- estudiantes2_long %>%
  unite(sexo_clase, sexo, clase, sep="-") %>%
  print
## # A tibble: 20 x 3
##     grade sexo_clase frecuencia
##  * <fctr>      <chr>      <int>
##  1      A     male-1          3
##  2      B     male-1          6
##  3      C     male-1          7
##  4      D     male-1          4
##  5      E     male-1          1
##  6      A   female-1          4
##  7      B   female-1          4
##  8      C   female-1          4
##  9      D   female-1          0
## 10      E   female-1          1
## 11      A     male-2          3
## 12      B     male-2          3
## 13      C     male-2          3
## 14      D     male-2          8
## 15      E     male-2          2
## 16      A   female-2          4
## 17      B   female-2          5
## 18      C   female-2          8
## 19      D   female-2          1
## 20      E   female-2          7