1.1 Comandos de filtro

El comando de filtro se utiliza para eliminar filas (registros) que no desea.

1.1.1 Filtro de condición única

library(tidyverse)
## ── Attaching packages ─────────────────────────────────────── tidyverse 1.3.1 ──
## ✓ ggplot2 3.3.5     ✓ purrr   0.3.4
## ✓ tibble  3.1.5     ✓ dplyr   1.0.7
## ✓ tidyr   1.1.4     ✓ stringr 1.4.0
## ✓ readr   2.0.2     ✓ forcats 0.5.1
## ── Conflicts ────────────────────────────────────────── tidyverse_conflicts() ──
## x dplyr::filter() masks stats::filter()
## x dplyr::lag()    masks stats::lag()
data("ChickWeight")
# Selecciona solo los datos de los pollos con 21 días
(twe_chi <- filter(ChickWeight, Time==21))
##    weight Time Chick Diet
## 1     205   21     1    1
## 2     215   21     2    1
## 3     202   21     3    1
## 4     157   21     4    1
## 5     223   21     5    1
## 6     157   21     6    1
## 7     305   21     7    1
## 8      98   21     9    1
## 9     124   21    10    1
## 10    175   21    11    1
## 11    205   21    12    1
## 12     96   21    13    1
## 13    266   21    14    1
## 14    142   21    17    1
## 15    157   21    19    1
## 16    117   21    20    1
## 17    331   21    21    2
## 18    167   21    22    2
## 19    175   21    23    2
## 20     74   21    24    2
## 21    265   21    25    2
## 22    251   21    26    2
## 23    192   21    27    2
## 24    233   21    28    2
## 25    309   21    29    2
## 26    150   21    30    2
## 27    256   21    31    3
## 28    305   21    32    3
## 29    147   21    33    3
## 30    341   21    34    3
## 31    373   21    35    3
## 32    220   21    36    3
## 33    178   21    37    3
## 34    290   21    38    3
## 35    272   21    39    3
## 36    321   21    40    3
## 37    204   21    41    4
## 38    281   21    42    4
## 39    200   21    43    4
## 40    196   21    45    4
## 41    238   21    46    4
## 42    205   21    47    4
## 43    322   21    48    4
## 44    237   21    49    4
## 45    264   21    50    4

NOTA: En el comando de filtro, “igual” se representa con doble igual“==”.

1.1.2 Filtro de condición múltiple

Se filtro el conjunto de datos ChickWeight con pollos de 21 días de edad y un peso superior a 121

(twe_chi_wei <- filter(ChickWeight, Time==21, weight>121))
##    weight Time Chick Diet
## 1     205   21     1    1
## 2     215   21     2    1
## 3     202   21     3    1
## 4     157   21     4    1
## 5     223   21     5    1
## 6     157   21     6    1
## 7     305   21     7    1
## 8     124   21    10    1
## 9     175   21    11    1
## 10    205   21    12    1
## 11    266   21    14    1
## 12    142   21    17    1
## 13    157   21    19    1
## 14    331   21    21    2
## 15    167   21    22    2
## 16    175   21    23    2
## 17    265   21    25    2
## 18    251   21    26    2
## 19    192   21    27    2
## 20    233   21    28    2
## 21    309   21    29    2
## 22    150   21    30    2
## 23    256   21    31    3
## 24    305   21    32    3
## 25    147   21    33    3
## 26    341   21    34    3
## 27    373   21    35    3
## 28    220   21    36    3
## 29    178   21    37    3
## 30    290   21    38    3
## 31    272   21    39    3
## 32    321   21    40    3
## 33    204   21    41    4
## 34    281   21    42    4
## 35    200   21    43    4
## 36    196   21    45    4
## 37    238   21    46    4
## 38    205   21    47    4
## 39    322   21    48    4
## 40    237   21    49    4
## 41    264   21    50    4

1.1.3 Filtros usando el operador lógico OR (|)

Se puede utilizar tantos símbolos OR (“|”) como sea necesario.

Filtro basado en el operador lógico OR:

(diet_twe_wei<- filter(ChickWeight, Diet== 2|Time==21))
##     weight Time Chick Diet
## 1      205   21     1    1
## 2      215   21     2    1
## 3      202   21     3    1
## 4      157   21     4    1
## 5      223   21     5    1
## 6      157   21     6    1
## 7      305   21     7    1
## 8       98   21     9    1
## 9      124   21    10    1
## 10     175   21    11    1
## 11     205   21    12    1
## 12      96   21    13    1
## 13     266   21    14    1
## 14     142   21    17    1
## 15     157   21    19    1
## 16     117   21    20    1
## 17      40    0    21    2
## 18      50    2    21    2
## 19      62    4    21    2
## 20      86    6    21    2
## 21     125    8    21    2
## 22     163   10    21    2
## 23     217   12    21    2
## 24     240   14    21    2
## 25     275   16    21    2
## 26     307   18    21    2
## 27     318   20    21    2
## 28     331   21    21    2
## 29      41    0    22    2
## 30      55    2    22    2
## 31      64    4    22    2
## 32      77    6    22    2
## 33      90    8    22    2
## 34      95   10    22    2
## 35     108   12    22    2
## 36     111   14    22    2
## 37     131   16    22    2
## 38     148   18    22    2
## 39     164   20    22    2
## 40     167   21    22    2
## 41      43    0    23    2
## 42      52    2    23    2
## 43      61    4    23    2
## 44      73    6    23    2
## 45      90    8    23    2
## 46     103   10    23    2
## 47     127   12    23    2
## 48     135   14    23    2
## 49     145   16    23    2
## 50     163   18    23    2
## 51     170   20    23    2
## 52     175   21    23    2
## 53      42    0    24    2
## 54      52    2    24    2
## 55      58    4    24    2
## 56      74    6    24    2
## 57      66    8    24    2
## 58      68   10    24    2
## 59      70   12    24    2
## 60      71   14    24    2
## 61      72   16    24    2
## 62      72   18    24    2
## 63      76   20    24    2
## 64      74   21    24    2
## 65      40    0    25    2
## 66      49    2    25    2
## 67      62    4    25    2
## 68      78    6    25    2
## 69     102    8    25    2
## 70     124   10    25    2
## 71     146   12    25    2
## 72     164   14    25    2
## 73     197   16    25    2
## 74     231   18    25    2
## 75     259   20    25    2
## 76     265   21    25    2
## 77      42    0    26    2
## 78      48    2    26    2
## 79      57    4    26    2
## 80      74    6    26    2
## 81      93    8    26    2
## 82     114   10    26    2
## 83     136   12    26    2
## 84     147   14    26    2
## 85     169   16    26    2
## 86     205   18    26    2
## 87     236   20    26    2
## 88     251   21    26    2
## 89      39    0    27    2
## 90      46    2    27    2
## 91      58    4    27    2
## 92      73    6    27    2
## 93      87    8    27    2
## 94     100   10    27    2
## 95     115   12    27    2
## 96     123   14    27    2
## 97     144   16    27    2
## 98     163   18    27    2
## 99     185   20    27    2
## 100    192   21    27    2
## 101     39    0    28    2
## 102     46    2    28    2
## 103     58    4    28    2
## 104     73    6    28    2
## 105     92    8    28    2
## 106    114   10    28    2
## 107    145   12    28    2
## 108    156   14    28    2
## 109    184   16    28    2
## 110    207   18    28    2
## 111    212   20    28    2
## 112    233   21    28    2
## 113     39    0    29    2
## 114     48    2    29    2
## 115     59    4    29    2
## 116     74    6    29    2
## 117     87    8    29    2
## 118    106   10    29    2
## 119    134   12    29    2
## 120    150   14    29    2
## 121    187   16    29    2
## 122    230   18    29    2
## 123    279   20    29    2
## 124    309   21    29    2
## 125     42    0    30    2
## 126     48    2    30    2
## 127     59    4    30    2
## 128     72    6    30    2
## 129     85    8    30    2
## 130     98   10    30    2
## 131    115   12    30    2
## 132    122   14    30    2
## 133    143   16    30    2
## 134    151   18    30    2
## 135    157   20    30    2
## 136    150   21    30    2
## 137    256   21    31    3
## 138    305   21    32    3
## 139    147   21    33    3
## 140    341   21    34    3
## 141    373   21    35    3
## 142    220   21    36    3
## 143    178   21    37    3
## 144    290   21    38    3
## 145    272   21    39    3
## 146    321   21    40    3
## 147    204   21    41    4
## 148    281   21    42    4
## 149    200   21    43    4
## 150    196   21    45    4
## 151    238   21    46    4
## 152    205   21    47    4
## 153    322   21    48    4
## 154    237   21    49    4
## 155    264   21    50    4

1.1.4 Filtrar usando mínimos, máximos o cualquier otro críterio númerico

(smallest_wei <- filter(ChickWeight, weight==min(weight)))
##   weight Time Chick Diet
## 1     35    2    18    1

En la salida del codigo se ve una sola fila con lo9s datos del menor peso de obtenido por los pollos

Filtrar con condiciones separadas por comas:

(chick.subset <- filter(ChickWeight, Time < 3, weight > 53))
##   weight Time Chick Diet
## 1     55    2    22    2
## 2     55    2    40    3
## 3     55    2    43    4
## 4     54    2    50    4

1.1.5 Filtrar valores perdidos (NAs) para una columna especifica

El conjunto de datos airquality presenta un valor faltan (NA) en la columna uno (Ozone)

Antes de filtrar los datos

data("airquality")
head(airquality,10)
##    Ozone Solar.R Wind Temp Month Day
## 1     41     190  7.4   67     5   1
## 2     36     118  8.0   72     5   2
## 3     12     149 12.6   74     5   3
## 4     18     313 11.5   62     5   4
## 5     NA      NA 14.3   56     5   5
## 6     28      NA 14.9   66     5   6
## 7     23     299  8.6   65     5   7
## 8     19      99 13.8   59     5   8
## 9      8      19 20.1   61     5   9
## 10    NA     194  8.6   69     5  10

Después de filtrar los datos

no.ozone = filter(airquality, !is.na(Ozone))
head(no.ozone,8)
##   Ozone Solar.R Wind Temp Month Day
## 1    41     190  7.4   67     5   1
## 2    36     118  8.0   72     5   2
## 3    12     149 12.6   74     5   3
## 4    18     313 11.5   62     5   4
## 5    28      NA 14.9   66     5   6
## 6    23     299  8.6   65     5   7
## 7    19      99 13.8   59     5   8
## 8     8      19 20.1   61     5   9

NOTA: Se elimino la fila que presentaba el NA en la columna de OZONE pero aun se encuentra el NA en la columna de Solar.R

1.1.6 Filtrar filas y NAs en cualquier parte del grupo de datos

Se usa complete.cases() para eliminar cualquier fila que contenga un NA en cualquier columna

(no_na <- filter(airquality[1:10,], complete.cases(airquality[1:10,])))
##   Ozone Solar.R Wind Temp Month Day
## 1    41     190  7.4   67     5   1
## 2    36     118  8.0   72     5   2
## 3    12     149 12.6   74     5   3
## 4    18     313 11.5   62     5   4
## 5    23     299  8.6   65     5   7
## 6    19      99 13.8   59     5   8
## 7     8      19 20.1   61     5   9

1.1.7 Filtrar con %in%

“%in%” es un operador que permite una forma abreviada para incluir o excluir valores especificados de una base de datos

data("iris")
table(iris$Species) #recuento de especies en el conjunto de datos, antes del filtrado
## 
##     setosa versicolor  virginica 
##         50         50         50
dos_especies <- filter(iris,Species %in% c("setosa", "virginica"))
table(dos_especies$Species)  #recuento de especies en el conjunto de datos, despues del filtrado
## 
##     setosa versicolor  virginica 
##         50          0         50

Número de filas antes y despues del filtrado

nrow(iris); nrow(dos_especies)
## [1] 150
## [1] 100

1.1.8 Filtrar el Ozone > 29 e incluir solo 3 columnas

data("airquality")
tres_columnas <- filter(airquality, Ozone > 29)[,1:3] #primero van las filas y luego las columnas
head(tres_columnas)
##   Ozone Solar.R Wind
## 1    41     190  7.4
## 2    36     118  8.0
## 3    34     307 12.0
## 4    30     322 11.5
## 5    32      92 12.0
## 6    45     252 14.9

1.1.9 Filtrar por Frecuencia total de un valor en todas las filas

group_by() permite el recuento de filas en función del número de engranajes. En la siguiente primera tabla, hay 15 registros con un automóvil que tiene tres marchas, 12 registros para cuatro marchas y cinco registros para cinco marchas.

table(mtcars$gear)
## 
##  3  4  5 
## 15 12  5

Después de aplicar el filtro y crear un nuevo marco de datos, no hay registros que tengan cinco engranajes:

engranaje <- mtcars %>%
 group_by(gear) %>%
 filter(n() > 10) #Una vez realizados los recuentos de engranajes, solo se incluyen en la salida aquellas filas cuyo recuento total supere los diez.
table(engranaje$gear) #Todo lo que desea ver aquí son registros que tienen al menos 11 filas con un número específico de marchas en el automóvil.
## 
##  3  4 
## 15 12

Se pueden agregar criterios adicionales al filtro :

potencia_motor<- mtcars %>%
group_by(gear) %>%
 filter(n() > 10, hp < 105)#se incluye el requisito de que la potencia sea inferior a 105
 table(potencia_motor$gear)
## 
## 3 4 
## 1 7

1.1.10 Filtrar por nombre de columna usando “starts with”

Se seleccionan las columnas con nombres que inicien con S

names(iris)#muestra los nombres de las columnas
## [1] "Sepal.Length" "Sepal.Width"  "Petal.Length" "Petal.Width"  "Species"
nombres_datos <- iris%>% dplyr::select(starts_with("S"))
head(nombres_datos)#Se utiliza head() para reducir el número de filas que se muestran en la salida del codigo
##   Sepal.Length Sepal.Width Species
## 1          5.1         3.5  setosa
## 2          4.9         3.0  setosa
## 3          4.7         3.2  setosa
## 4          4.6         3.1  setosa
## 5          5.0         3.6  setosa
## 6          5.4         3.9  setosa

1.1.11 Filtrar filas: las columnas cumplen con el criterio (filter_at)

Se utiliza filter_at () para buscar filas que cumplan con algunos criterios al pasar por el filtro de datos.

(new.mt <- mtcars %>% filter_at(vars(cyl, hp),
   all_vars(. == max(.))))
##               mpg cyl disp  hp drat   wt qsec vs am gear carb
## Maserati Bora  15   8  301 335 3.54 3.57 14.6  0  1    5    8

Otro ejemplo que puede verse es con la base de datos de Suzan Baert:

(msleep<-ggplot2::msleep)
## # A tibble: 83 × 11
##    name   genus vore  order conservation sleep_total sleep_rem sleep_cycle awake
##    <chr>  <chr> <chr> <chr> <chr>              <dbl>     <dbl>       <dbl> <dbl>
##  1 Cheet… Acin… carni Carn… lc                  12.1      NA        NA      11.9
##  2 Owl m… Aotus omni  Prim… <NA>                17         1.8      NA       7  
##  3 Mount… Aplo… herbi Rode… nt                  14.4       2.4      NA       9.6
##  4 Great… Blar… omni  Sori… lc                  14.9       2.3       0.133   9.1
##  5 Cow    Bos   herbi Arti… domesticated         4         0.7       0.667  20  
##  6 Three… Brad… herbi Pilo… <NA>                14.4       2.2       0.767   9.6
##  7 North… Call… carni Carn… vu                   8.7       1.4       0.383  15.3
##  8 Vespe… Calo… <NA>  Rode… <NA>                 7        NA        NA      17  
##  9 Dog    Canis carni Carn… domesticated        10.1       2.9       0.333  13.9
## 10 Roe d… Capr… herbi Arti… lc                   3        NA        NA      21  
## # … with 73 more rows, and 2 more variables: brainwt <dbl>, bodywt <dbl>
(msleep.over.5 <- msleep %>%
  select(name, sleep_total:sleep_rem, brainwt:bodywt) %>%
  filter_at(vars(contains("sleep")), #La función filter_at dice que mire solo las variables que contienen la palabra "sleep".
            all_vars(.>5))) #El "." significa cualquier variable con dormir en el nombre.
## # A tibble: 2 × 5
##   name                 sleep_total sleep_rem brainwt bodywt
##   <chr>                      <dbl>     <dbl>   <dbl>  <dbl>
## 1 Thick-tailed opposum        19.4       6.6  NA       0.37
## 2 Giant armadillo             18.1       6.1   0.081  60

1.2 Arrange (Sort)

La función arrange() reordena un vector o un dataframe en una secuencia definida que puede ser ascendente o descendente.

msleep<-ggplot2::msleep
msleep[,1:4]
## # A tibble: 83 × 4
##    name                       genus       vore  order       
##    <chr>                      <chr>       <chr> <chr>       
##  1 Cheetah                    Acinonyx    carni Carnivora   
##  2 Owl monkey                 Aotus       omni  Primates    
##  3 Mountain beaver            Aplodontia  herbi Rodentia    
##  4 Greater short-tailed shrew Blarina     omni  Soricomorpha
##  5 Cow                        Bos         herbi Artiodactyla
##  6 Three-toed sloth           Bradypus    herbi Pilosa      
##  7 Northern fur seal          Callorhinus carni Carnivora   
##  8 Vesper mouse               Calomys     <NA>  Rodentia    
##  9 Dog                        Canis       carni Carnivora   
## 10 Roe deer                   Capreolus   herbi Artiodactyla
## # … with 73 more rows

1.2.1 Ascendente

animal1<- arrange(msleep, vore, order)
animal1[,1:4]
## # A tibble: 83 × 4
##    name              genus        vore  order    
##    <chr>             <chr>        <chr> <chr>    
##  1 Cheetah           Acinonyx     carni Carnivora
##  2 Northern fur seal Callorhinus  carni Carnivora
##  3 Dog               Canis        carni Carnivora
##  4 Domestic cat      Felis        carni Carnivora
##  5 Gray seal         Haliochoerus carni Carnivora
##  6 Tiger             Panthera     carni Carnivora
##  7 Jaguar            Panthera     carni Carnivora
##  8 Lion              Panthera     carni Carnivora
##  9 Caspian seal      Phoca        carni Carnivora
## 10 Genet             Genetta      carni Carnivora
## # … with 73 more rows

1.2.2 Descendente

animal2 <- arrange(msleep, vore, desc(order))
head(animal2[,1:4])
## # A tibble: 6 × 4
##   name                       genus         vore  order          
##   <chr>                      <chr>         <chr> <chr>          
## 1 Northern grasshopper mouse Onychomys     carni Rodentia       
## 2 Slow loris                 Nyctibeus     carni Primates       
## 3 Thick-tailed opposum       Lutreolina    carni Didelphimorphia
## 4 Long-nosed armadillo       Dasypus       carni Cingulata      
## 5 Pilot whale                Globicephalus carni Cetacea        
## 6 Common porpoise            Phocoena      carni Cetacea

1.3 Rename

rename() permite cambiar el nombre de una o más columnas. Es una función de conveniencia y no cambia datos.

names(iris) 
## [1] "Sepal.Length" "Sepal.Width"  "Petal.Length" "Petal.Width"  "Species"

Muestra los nuevos nombres de las columnas

iris_renombre <- rename(iris, width.of.petals = Petal.Width,
various.plants.and.animals = Species)
names(iris_renombre)
## [1] "Sepal.Length"               "Sepal.Width"               
## [3] "Petal.Length"               "width.of.petals"           
## [5] "various.plants.and.animals"

1.4 Mutate

mutate() agrega nuevas variables a un marco de datos.

Chickweight.with.log <- mutate(ChickWeight, #Requiere el marco de datos original como primer argumento
log.of.weight = log10(weight))#luego los argumentos para crear nuevas variables como los argumentos restantes.
Chickweight.with.log[1:2,]
##   weight Time Chick Diet log.of.weight
## 1     42    0     1    1      1.623249
## 2     51    2     1    1      1.707570

1.4.1 mutate_all para agregar nuevos campos de una vez

msleep <- ggplot2::msleep #marco de datos msleep del paquete ggplot2
names(msleep)
##  [1] "name"         "genus"        "vore"         "order"        "conservation"
##  [6] "sleep_total"  "sleep_rem"    "sleep_cycle"  "awake"        "brainwt"     
## [11] "bodywt"
raiz_msleep<- mutate_all(msleep[,6:11], #cada una de las columnas designadas (6–11) proporciona números a la función de raíz cuadrada
  funs("square root" = sqrt( . ))) #nueva columna con el sufijo square root
## Warning: `funs()` was deprecated in dplyr 0.8.0.
## Please use a list of either functions or lambdas: 
## 
##   # Simple named list: 
##   list(mean = mean, median = median)
## 
##   # Auto named with `tibble::lst()`: 
##   tibble::lst(mean, median)
## 
##   # Using lambdas
##   list(~ mean(., trim = .2), ~ median(., na.rm = TRUE))
## This warning is displayed once every 8 hours.
## Call `lifecycle::last_lifecycle_warnings()` to see where this warning was generated.
names(raiz_msleep)
##  [1] "sleep_total"             "sleep_rem"              
##  [3] "sleep_cycle"             "awake"                  
##  [5] "brainwt"                 "bodywt"                 
##  [7] "sleep_total_square root" "sleep_rem_square root"  
##  [9] "sleep_cycle_square root" "awake_square root"      
## [11] "brainwt_square root"     "bodywt_square root"
raiz_msleep
## # A tibble: 83 × 12
##    sleep_total sleep_rem sleep_cycle awake  brainwt  bodywt `sleep_total_square…
##          <dbl>     <dbl>       <dbl> <dbl>    <dbl>   <dbl>                <dbl>
##  1        12.1      NA        NA      11.9 NA        50                     3.48
##  2        17         1.8      NA       7    0.0155    0.48                  4.12
##  3        14.4       2.4      NA       9.6 NA         1.35                  3.79
##  4        14.9       2.3       0.133   9.1  0.00029   0.019                 3.86
##  5         4         0.7       0.667  20    0.423   600                     2   
##  6        14.4       2.2       0.767   9.6 NA         3.85                  3.79
##  7         8.7       1.4       0.383  15.3 NA        20.5                   2.95
##  8         7        NA        NA      17   NA         0.045                 2.65
##  9        10.1       2.9       0.333  13.9  0.07     14                     3.18
## 10         3        NA        NA      21    0.0982   14.8                   1.73
## # … with 73 more rows, and 5 more variables: sleep_rem_square root <dbl>,
## #   sleep_cycle_square root <dbl>, awake_square root <dbl>,
## #   brainwt_square root <dbl>, bodywt_square root <dbl>

1.4.2 mutate_at para añadir campos

data("Titanic") #Se utiliza el conjunto de datos Titanic
Titanic <- as.data.frame(Titanic) #as.data.frame() se usa para convertir a un marco de datos
head(Titanic)
##   Class    Sex   Age Survived Freq
## 1   1st   Male Child       No    0
## 2   2nd   Male Child       No    0
## 3   3rd   Male Child       No   35
## 4  Crew   Male Child       No    0
## 5   1st Female Child       No    0
## 6   2nd Female Child       No    0
clasificacion_titanic <- mutate_at(Titanic, vars(Class,Age,Survived), #las variables con rangos de datos se crean con mutate_at() 
funs(Rank = min_rank(desc(.))))
head(clasificacion_titanic)
##   Class    Sex   Age Survived Freq Class_Rank Age_Rank Survived_Rank
## 1   1st   Male Child       No    0         25       17            17
## 2   2nd   Male Child       No    0         17       17            17
## 3   3rd   Male Child       No   35          9       17            17
## 4  Crew   Male Child       No    0          1       17            17
## 5   1st Female Child       No    0         25       17            17
## 6   2nd Female Child       No    0         17       17            17

1.4.3 mutate_if

La función mutate_if() combina el operador lógico if y mutate() para crear una nueva variable o alterar una ya existente.

EJEMPLO 1

div10 <- function (a.number) (a.number / 10) #funcion para dividir un numero en 10
head(CO2) #Se utiliza el conjunto de datos CO2
##   Plant   Type  Treatment conc uptake
## 1   Qn1 Quebec nonchilled   95   16.0
## 2   Qn1 Quebec nonchilled  175   30.4
## 3   Qn1 Quebec nonchilled  250   34.8
## 4   Qn1 Quebec nonchilled  350   37.2
## 5   Qn1 Quebec nonchilled  500   35.3
## 6   Qn1 Quebec nonchilled  675   39.2
new.df <- CO2 %>%
 mutate_if(is.numeric, div10) #Ahora se divide cualquier columna que tenga un formato numérico por 10, utilizando la función creada anteriormente, div10
head(new.df)
##   Plant   Type  Treatment conc uptake
## 1   Qn1 Quebec nonchilled  9.5   1.60
## 2   Qn1 Quebec nonchilled 17.5   3.04
## 3   Qn1 Quebec nonchilled 25.0   3.48
## 4   Qn1 Quebec nonchilled 35.0   3.72
## 5   Qn1 Quebec nonchilled 50.0   3.53
## 6   Qn1 Quebec nonchilled 67.5   3.92

EJEMPLO 2

(df <- data.frame(
alpha = c(22, 1, NA),
almond = c(0, 5, 10),
grape = c(0, 2, 2),
apple = c(NA, 5, 10))) 
##   alpha almond grape apple
## 1    22      0     0    NA
## 2     1      5     2     5
## 3    NA     10     2    10
(df.sin.NA <- df %>% mutate_if(is.numeric, #Cualquier NA en un campo numérico se reemplaza por cero
                                 coalesce, ... = 0))  #“Coalesce” es una función  que encuentra el primer valor presente después de un NA.
##   alpha almond grape apple
## 1    22      0     0     0
## 2     1      5     2     5
## 3     0     10     2    10

1.4.4 String Detect and True/False Duplicate Indicator

Todas las columnas con los caracteres sleep en el nombre de la columna serán convertidos a caracter.

msleep<-ggplot2::msleep
table(msleep$vore)
## 
##   carni   herbi insecti    omni 
##      19      32       5      20
msleep.no.c.or.a <- filter(msleep, !str_detect(vore,
   paste(c("c","a"), collapse = "|")))
table(msleep.no.c.or.a$vore)
## 
## herbi  omni 
##    32    20
msleep.doble.ind <- mutate(msleep, duplicate.indicator = 
duplicated(conservation)) #Se agrego un campo que indique si un valor particular en una columna ocurre más de una vez. En este caso, la columna es conservation
msleep.doble.ind[1:6,]
## # A tibble: 6 × 12
##   name    genus vore  order conservation sleep_total sleep_rem sleep_cycle awake
##   <chr>   <chr> <chr> <chr> <chr>              <dbl>     <dbl>       <dbl> <dbl>
## 1 Cheetah Acin… carni Carn… lc                  12.1      NA        NA      11.9
## 2 Owl mo… Aotus omni  Prim… <NA>                17         1.8      NA       7  
## 3 Mounta… Aplo… herbi Rode… nt                  14.4       2.4      NA       9.6
## 4 Greate… Blar… omni  Sori… lc                  14.9       2.3       0.133   9.1
## 5 Cow     Bos   herbi Arti… domesticated         4         0.7       0.667  20  
## 6 Three-… Brad… herbi Pilo… <NA>                14.4       2.2       0.767   9.6
## # … with 3 more variables: brainwt <dbl>, bodywt <dbl>,
## #   duplicate.indicator <lgl>

Otra forma de escribir lo anterior es:

(msleep.doble.ind2 <- mutate(msleep,
 duplicate.indicator = duplicated(conservation, genus)) %>%
 arrange(conservation,genus))
## # A tibble: 83 × 12
##    name   genus vore  order conservation sleep_total sleep_rem sleep_cycle awake
##    <chr>  <chr> <chr> <chr> <chr>              <dbl>     <dbl>       <dbl> <dbl>
##  1 Giraf… Gira… herbi Arti… cd                   1.9       0.4      NA      22.1
##  2 Pilot… Glob… carni Ceta… cd                   2.7       0.1      NA      21.4
##  3 Cow    Bos   herbi Arti… domesticated         4         0.7       0.667  20  
##  4 Dog    Canis carni Carn… domesticated        10.1       2.9       0.333  13.9
##  5 Guine… Cavis herbi Rode… domesticated         9.4       0.8       0.217  14.6
##  6 Chinc… Chin… herbi Rode… domesticated        12.5       1.5       0.117  11.5
##  7 Horse  Equus herbi Peri… domesticated         2.9       0.6       1      21.1
##  8 Donkey Equus herbi Peri… domesticated         3.1       0.4      NA      20.9
##  9 Domes… Felis carni Carn… domesticated        12.5       3.2       0.417  11.5
## 10 Rabbit Oryc… herbi Lago… domesticated         8.4       0.9       0.417  15.6
## # … with 73 more rows, and 3 more variables: brainwt <dbl>, bodywt <dbl>,
## #   duplicate.indicator <lgl>

NOTA: Tanto conservation y genus deben duplicarse para que duplicate.indicator() se establezca en TRUE.

fruit <- c("apple","pear","orange","grape", "orange","orange")
x <- c(1,2,4,9,4,6)
y <- c(22,3,4,55,15,9)
z <- c(3,1,4,10,12,8)
w <- c(2,2,2,4,5,6)
(fruta<-data.frame(fruit,x,y,z,w)) #Se creo un data frame con nombres de frutas
##    fruit x  y  z w
## 1  apple 1 22  3 2
## 2   pear 2  3  1 2
## 3 orange 4  4  4 2
## 4  grape 9 55 10 4
## 5 orange 4 15 12 5
## 6 orange 6  9  8 6
#Se utilizan las funciones mutate() y duplicate.indicator en el data frame creado anteriormente
(fruta_dup <- mutate(fruta, duplicate.indicator = duplicated(fruit)))
##    fruit x  y  z w duplicate.indicator
## 1  apple 1 22  3 2               FALSE
## 2   pear 2  3  1 2               FALSE
## 3 orange 4  4  4 2               FALSE
## 4  grape 9 55 10 4               FALSE
## 5 orange 4 15 12 5                TRUE
## 6 orange 6  9  8 6                TRUE

NOTA: DPLYR baja por las filas y observa los valores de la columna “fruta”. No puede detectar el primer dato duplicado porque aún no sabe si hay otro. Cuando ve “orange” por segunda y tercera vez, establece la columna duplicate.indicator() como “TRUE” para las filas que contienen el valor “orange”. Si se desea verificar varios campos, se usa mutate() para combinarlos en un nuevo campo antes de usar el indicador lógico duplicado (TRUE / False)

1.4.5 Omitir variables usando NULL

fruit <- c("apple","pear","orange","grape", "orange","orange")
x <- c(1,2,4,9,4,6)
y <- c(22,3,4,55,15,9)
z <- c(3,1,4,10,12,8)
df <- data.frame(fruit,x,y,z)
(df <- mutate(df, z = NULL))
##    fruit x  y
## 1  apple 1 22
## 2   pear 2  3
## 3 orange 4  4
## 4  grape 9 55
## 5 orange 4 15
## 6 orange 6  9

1.4.6 Secuencia de codificación recomendada

Forma de usar mutate() dentro de este misma función

NO RECOMENDADO

if (!require("nycflights13")) install.packages("nycflights13")
## Loading required package: nycflights13
mutate(flights,
 gain = arr_delay - dep_delay,
 hours = air_time / 60,
 gain_per_hour = gain / hours,
 gain_per_minute = 60 * gain_per_hour)
## # A tibble: 336,776 × 23
##     year month   day dep_time sched_dep_time dep_delay arr_time sched_arr_time
##    <int> <int> <int>    <int>          <int>     <dbl>    <int>          <int>
##  1  2013     1     1      517            515         2      830            819
##  2  2013     1     1      533            529         4      850            830
##  3  2013     1     1      542            540         2      923            850
##  4  2013     1     1      544            545        -1     1004           1022
##  5  2013     1     1      554            600        -6      812            837
##  6  2013     1     1      554            558        -4      740            728
##  7  2013     1     1      555            600        -5      913            854
##  8  2013     1     1      557            600        -3      709            723
##  9  2013     1     1      557            600        -3      838            846
## 10  2013     1     1      558            600        -2      753            745
## # … with 336,766 more rows, and 15 more variables: arr_delay <dbl>,
## #   carrier <chr>, flight <int>, tailnum <chr>, origin <chr>, dest <chr>,
## #   air_time <dbl>, distance <dbl>, hour <dbl>, minute <dbl>, time_hour <dttm>,
## #   gain <dbl>, hours <dbl>, gain_per_hour <dbl>, gain_per_minute <dbl>

RECOMENDADO

if (!require("nycflights13")) install.packages("nycflights13")
newfield.flights <- flights %>%
  mutate(gain = arr_delay - dep_delay,
  hours = air_time / 60) %>%
  mutate(gain_per_hour = gain / hours) %>%
  mutate(gain_per_minute = 60 * gain_per_hour)
newfield.flights[1:6,c(1:2,20:23)] #Muestra las columnas seleccionadas para las primeras seis filas, incluidas las recién creadas.
## # A tibble: 6 × 6
##    year month  gain hours gain_per_hour gain_per_minute
##   <int> <int> <dbl> <dbl>         <dbl>           <dbl>
## 1  2013     1     9  3.78          2.38            143.
## 2  2013     1    16  3.78          4.23            254.
## 3  2013     1    31  2.67         11.6             698.
## 4  2013     1   -17  3.05         -5.57           -334.
## 5  2013     1   -19  1.93         -9.83           -590.
## 6  2013     1    16  2.5           6.4             384

1.4.7 Transmute: mantiene solo algunas variables creadas

La función trasmute() permite crear un marco de datos completamente nuevo basado en cálculos realizados en variables existentes.

fruit <- c("apple","pear","orange","grape", "orange","orange")
x <- c(1,2,4,9,4,6)
y <- c(22,3,4,55,15,9)
z <- c(3,1,4,10,12,8)
(fruta1 <- data.frame(fruit,x,y,z)) #Antes de usar trasmute()
##    fruit x  y  z
## 1  apple 1 22  3
## 2   pear 2  3  1
## 3 orange 4  4  4
## 4  grape 9 55 10
## 5 orange 4 15 12
## 6 orange 6  9  8
(df <- transmute(df, new.variable = x + y + z)) #Despues de usar trasmute()
##   new.variable
## 1           26
## 2            6
## 3           12
## 4           74
## 5           31
## 6           23

1.4.8 Usar Acroos para aplicar una función sobre múltiples columnas

double.it <- function(x) x*2 #función simple para duplicar el valor de un número
head(iris)
##   Sepal.Length Sepal.Width Petal.Length Petal.Width Species
## 1          5.1         3.5          1.4         0.2  setosa
## 2          4.9         3.0          1.4         0.2  setosa
## 3          4.7         3.2          1.3         0.2  setosa
## 4          4.6         3.1          1.5         0.2  setosa
## 5          5.0         3.6          1.4         0.2  setosa
## 6          5.4         3.9          1.7         0.4  setosa
iris %>%
 mutate(across(where(is.numeric), double.it)) %>%
 head() #Muestra un nuevo marco de datos de "iris" con valores duplicados para las columnas numéricas
##   Sepal.Length Sepal.Width Petal.Length Petal.Width Species
## 1         10.2         7.0          2.8         0.4  setosa
## 2          9.8         6.0          2.8         0.4  setosa
## 3          9.4         6.4          2.6         0.4  setosa
## 4          9.2         6.2          3.0         0.4  setosa
## 5         10.0         7.2          2.8         0.4  setosa
## 6         10.8         7.8          3.4         0.8  setosa

1.4.9 Conditional Mutating usando case_when

case_when() puede mutar un nuevo campo y luego establecer valores basados en múltiples condiciones.

row1 <- c("a","b","c","d","e","f","column.to.be.changed")
row2 <- c(1,1,1,6,6,1,2)
row3 <- c(3,4,4,6,4,4,4)
row4 <- c(4,6,25,5,5,2,9)
row5 <- c(5,3,6,3,3,6,2)
df1 <- as.data.frame(rbind(row2,row3,row4,row5))
names(df1) <- row1
df1
##      a b  c d e f column.to.be.changed
## row2 1 1  1 6 6 1                    2
## row3 3 4  4 6 4 4                    4
## row4 4 6 25 5 5 2                    9
## row5 5 3  6 3 3 6                    2
(new.df <-df1 %>%
 mutate(columna.cambiada= case_when(a == 2 | a == 5 |
 a == 7 | (a == 1 & b == 4) ~ 2, a == 0 | a == 1 | a == 4 |
 a == 3 | c == 4 ~ 3, TRUE ~ NA_real_))) #Esta es una serie de condiciones "OR". Si alguno de ellos es "TRUE", entonces la última columna (columna.cambiada) será un 2 o un 3
##      a b  c d e f column.to.be.changed columna.cambiada
## row2 1 1  1 6 6 1                    2                3
## row3 3 4  4 6 4 4                    4                3
## row4 4 6 25 5 5 2                    9                3
## row5 5 3  6 3 3 6                    2                2

1.5 Select Select para escoger variables/columnas

select() conserva solo las variables que incluye dentro de esta declaración. La función rename, comunmente mencionada como una función hermana de select(), no elimina ninguna variable. ### 1.5.1 Eliminar una columna

fruta1 #Antes de utilizar select()
##    fruit x  y  z
## 1  apple 1 22  3
## 2   pear 2  3  1
## 3 orange 4  4  4
## 4  grape 9 55 10
## 5 orange 4 15 12
## 6 orange 6  9  8
(no.fruit <- dplyr::select(fruta1, -fruit))#Se coloca un signo menos delante de cualquier variable que se desee eliminar. La columna con los nombres de frutas no se incluye en el nuevo marco de datos.
##   x  y  z
## 1 1 22  3
## 2 2  3  1
## 3 4  4  4
## 4 9 55 10
## 5 4 15 12
## 6 6  9  8

1.5.2 Eliminar una columna con nombre usando stars_with o ends_with

Se utiliza la función names() para enunciar los nombres de las columnas del marco de datos

names(mtcars)#
##  [1] "mpg"  "cyl"  "disp" "hp"   "drat" "wt"   "qsec" "vs"   "am"   "gear"
## [11] "carb"
col.sin.d <- select(mtcars,-starts_with("d")) #Elimina las columnas cuyos nombres comiencen con una "d":
names(col.sin.d)
## [1] "mpg"  "cyl"  "hp"   "wt"   "qsec" "vs"   "am"   "gear" "carb"
col.names <- select(mtcars, -ends_with("t"))#Elimina las columnas cuyos nombres terminen en "t"
names(col.names)
## [1] "mpg"  "cyl"  "disp" "hp"   "qsec" "vs"   "am"   "gear" "carb"

1.5.3 Reordenar una columna

fruit <- c("apple","pear","orange","grape", "orange","orange")
x <- c(1,2,4,9,4,6)
y <- c(22,3,4,55,15,9)
z <- c(3,1,4,10,12,8)
(fruta2 <- data.frame(fruit,x,y,z))
##    fruit x  y  z
## 1  apple 1 22  3
## 2   pear 2  3  1
## 3 orange 4  4  4
## 4  grape 9 55 10
## 5 orange 4 15 12
## 6 orange 6  9  8

NOTA:Esta acción mueve la columna z a la izquierda de todo lo demás y se convierte en la primera columna. A menudo es más conveniente tener columnas de uso frecuente a la izquierda. La palabra clave “everything” significa que todas las columnas restantes deben conservarse.

1.5.4 select_all para aplicar una función a todas las columnas

Se utiliza select_all() para aplicar una función a todas las columnas.

state <- c("Maryland", "Alaska", "New Jersey")
income <- c(76067,74444,73702)
median.us <- c(61372,61372,61372)
life.expectancy <- c(78.8,78.3,80.3)
(top.3.states <- data.frame(state, income, median.us,
 life.expectancy)) #Antes de aplicar la función select_all() los nombres de las columnas no están en mayúscula
##        state income median.us life.expectancy
## 1   Maryland  76067     61372            78.8
## 2     Alaska  74444     61372            78.3
## 3 New Jersey  73702     61372            80.3

Tambien se puede usar la función toupper() para colocar en mayúsculas los nombres de las columnas

(new.top.3.states <- select_all(top.3.states, toupper))
##        STATE INCOME MEDIAN.US LIFE.EXPECTANCY
## 1   Maryland  76067     61372            78.8
## 2     Alaska  74444     61372            78.3
## 3 New Jersey  73702     61372            80.3

1.5.5 Seleccionar columnas usando la función Pull

La función pull() aisla una columna especifica y actua similar a la sintaxis de R $

(top.3.states <- data.frame(state, income, median.us, life.expectancy))
##        state income median.us life.expectancy
## 1   Maryland  76067     61372            78.8
## 2     Alaska  74444     61372            78.3
## 3 New Jersey  73702     61372            80.3
(pull.first.column <- pull(top.3.states,1)) #Para extraer la primera columna de datos
## [1] "Maryland"   "Alaska"     "New Jersey"
(pull.last.column <- pull(top.3.states,-1)) #Se usa un número negativo para extraer una columna de la derecha, es decir, -1 = columna más a la derecha
## [1] 78.8 78.3 80.3

1.5.6 Seleccionar filas: cualquier variable que cumpla una condición

nrow(mtcars) #se usa para saber el numero de filas originales del dataframe
## [1] 32

El siguiente código filtra cualquier elemento del conjunto de datos superior a 200, en cualquier columna.

(mtcars200 <- filter_all(mtcars, any_vars(. > 200)))
##                      mpg cyl  disp  hp drat    wt  qsec vs am gear carb
## Hornet 4 Drive      21.4   6 258.0 110 3.08 3.215 19.44  1  0    3    1
## Hornet Sportabout   18.7   8 360.0 175 3.15 3.440 17.02  0  0    3    2
## Valiant             18.1   6 225.0 105 2.76 3.460 20.22  1  0    3    1
## Duster 360          14.3   8 360.0 245 3.21 3.570 15.84  0  0    3    4
## Merc 450SE          16.4   8 275.8 180 3.07 4.070 17.40  0  0    3    3
## Merc 450SL          17.3   8 275.8 180 3.07 3.730 17.60  0  0    3    3
## Merc 450SLC         15.2   8 275.8 180 3.07 3.780 18.00  0  0    3    3
## Cadillac Fleetwood  10.4   8 472.0 205 2.93 5.250 17.98  0  0    3    4
## Lincoln Continental 10.4   8 460.0 215 3.00 5.424 17.82  0  0    3    4
## Chrysler Imperial   14.7   8 440.0 230 3.23 5.345 17.42  0  0    3    4
## Dodge Challenger    15.5   8 318.0 150 2.76 3.520 16.87  0  0    3    2
## AMC Javelin         15.2   8 304.0 150 3.15 3.435 17.30  0  0    3    2
## Camaro Z28          13.3   8 350.0 245 3.73 3.840 15.41  0  0    3    4
## Pontiac Firebird    19.2   8 400.0 175 3.08 3.845 17.05  0  0    3    2
## Ford Pantera L      15.8   8 351.0 264 4.22 3.170 14.50  0  1    5    4
## Maserati Bora       15.0   8 301.0 335 3.54 3.570 14.60  0  1    5    8

1.5.7 Seleccionar columnas: omitir la columna si el nombre contiene caracteres especificos

names(mtcars)
##  [1] "mpg"  "cyl"  "disp" "hp"   "drat" "wt"   "qsec" "vs"   "am"   "gear"
## [11] "carb"
cars_sin_p<-mtcars %>%
  dplyr::select(-contains("p")) #Se Seleccionaron columnas que no tuvieran "p" en su nombre
names(cars_sin_p) #No se incluye ningún nombre de columna que tenga "p" en el nuevo marco de datos.
## [1] "cyl"  "drat" "wt"   "qsec" "vs"   "am"   "gear" "carb"

1.5.8 Seleccionar la coincidencia de comodines

names(mtcars)
##  [1] "mpg"  "cyl"  "disp" "hp"   "drat" "wt"   "qsec" "vs"   "am"   "gear"
## [11] "carb"
subset.mtcars <- select(mtcars,
 matches("pg|gea")) #Los nombres de columna seleccionados contienen los caracteres "pg" o "gea"
names(subset.mtcars)
## [1] "mpg"  "gear"

NOTA: La función “matches()” es más general que “contains” porque es una expresión regular y más flexible.

1.6 Joins: Modificación de datos de dos fuentes

Las conexiones entre tablas se hacen usando “llaves” definidas. Si tengo una tabla A con US state abbrevation y población por estado; y la tabla B contiene Us state abbreviation y el nombre completo del estado. Si se quiere crear un nuevo dataframe que tenga el nombre completo del estado y la poblacion del estado se debe tomar, la abreviación del estado de la tabla A como la llave primaria y la breviación del estado en la tabla B como una llave foranea.

1.6.1 Left Join (Mas comun)

La función left_join() busca datos que coinciden entre ambos archivos usando una “llave” (by=“key”)

(us.state.areas <- as.data.frame(cbind(state.abb, state.area)))
##    state.abb state.area
## 1         AL      51609
## 2         AK     589757
## 3         AZ     113909
## 4         AR      53104
## 5         CA     158693
## 6         CO     104247
## 7         CT       5009
## 8         DE       2057
## 9         FL      58560
## 10        GA      58876
## 11        HI       6450
## 12        ID      83557
## 13        IL      56400
## 14        IN      36291
## 15        IA      56290
## 16        KS      82264
## 17        KY      40395
## 18        LA      48523
## 19        ME      33215
## 20        MD      10577
## 21        MA       8257
## 22        MI      58216
## 23        MN      84068
## 24        MS      47716
## 25        MO      69686
## 26        MT     147138
## 27        NE      77227
## 28        NV     110540
## 29        NH       9304
## 30        NJ       7836
## 31        NM     121666
## 32        NY      49576
## 33        NC      52586
## 34        ND      70665
## 35        OH      41222
## 36        OK      69919
## 37        OR      96981
## 38        PA      45333
## 39        RI       1214
## 40        SC      31055
## 41        SD      77047
## 42        TN      42244
## 43        TX     267339
## 44        UT      84916
## 45        VT       9609
## 46        VA      40815
## 47        WA      68192
## 48        WV      24181
## 49        WI      56154
## 50        WY      97914
abbreviation.name <- as.data.frame(cbind(state.abb, state.name))
abbreviation.name[1:3,]
##   state.abb state.name
## 1        AL    Alabama
## 2        AK     Alaska
## 3        AZ    Arizona
info.area.name <- us.state.areas %>%
 left_join(abbreviation.name, by = "state.abb") #Se uso la función left_join() para unir los 2 marco de datos
head(info.area.name)
##   state.abb state.area state.name
## 1        AL      51609    Alabama
## 2        AK     589757     Alaska
## 3        AZ     113909    Arizona
## 4        AR      53104   Arkansas
## 5        CA     158693 California
## 6        CO     104247   Colorado

1.6.2 Inner Join

La función inner_join() genera solo las filas en ambos marcos de datos cuando la llave o clave son la misma. Todas las demás filas se eliminan.

#Primer data frame
names <- c("Sally","Tom","Frieda","Alfonzo")
team.scores <- c(3,5,2,7)
team.league <- c("alpha","beta","gamma", "omicron")
team.info <- data.frame(names, team.scores, team.league)
#Segundo data frame
names = c("Sally","Tom", "Bill", "Alfonzo")
school.grades <- c("A","B","C","B")
school.info <- data.frame(names, school.grades)
(school.and.team <- inner_join(team.info, school.info, by = "names")) #Los datos aparecen en el marco de datos de la escuela y el equipo solo cuando los nombres coinciden exactamente.
##     names team.scores team.league school.grades
## 1   Sally           3       alpha             A
## 2     Tom           5        beta             B
## 3 Alfonzo           7     omicron             B

1.6.3 Anti-join

La función anti_join() filtra filas del X basado en la presencia o ausencia de conincidencias en el Y.

#Primer data frame
names <- c("Sally","Tom","Frieda","Alfonzo")
team.scores <- c(3,5,2,7)
team.league <- c("alpha","beta","gamma", "omicron")
team.info <- data.frame(names, team.scores, team.league)
#Segundo data frame
names <- c("Sally","Tom", "Bill", "Alfonzo")
school.grades <- c("A","B","C","B")
(school.info <- data.frame(names, school.grades))
##     names school.grades
## 1   Sally             A
## 2     Tom             B
## 3    Bill             C
## 4 Alfonzo             B
(nogrades <- anti_join(team.info, school.info, by = "names")) #Los datos provienen de team.info, pero solo se muestran los nombres que NO coinciden con los datos de calificaciones.
##    names team.scores team.league
## 1 Frieda           2       gamma

1.6.4 Full Join

La función full_join() conserva todos los valores de ambos marcos de datos.

#Primer data frame
names = c("Sally","Tom","Frieda","Alfonzo")
team.scores = c(3,5,2,7)
team.league = c("alpha","beta","gamma", "omicron")
team.info = data.frame(names, team.scores, team.league)
#Segundo data frame
names = c("Sally","Tom", "Bill", "Alfonzo")
school.grades = c("A","B","C","B")
school.info = data.frame(names, school.grades)
(team.info.and.or.grades <- full_join(team.info, school.info, by = "names"))#Se creo un nuevo data frame utilizando la full join ()
##     names team.scores team.league school.grades
## 1   Sally           3       alpha             A
## 2     Tom           5        beta             B
## 3  Frieda           2       gamma          <NA>
## 4 Alfonzo           7     omicron             B
## 5    Bill          NA        <NA>             C

1.6.5 Semi-join

La función semi_join() conserva todos las observaciones del grupo de datos 1 que coinciden con el grupo de datos 2. El orden en que se pongan los marcos de datos determinara el resultado.

(team.info.with.grades <- semi_join(team.info, school.info)) # DPLYR comprende que "names" es una clave común. 
## Joining, by = "names"
##     names team.scores team.league
## 1   Sally           3       alpha
## 2     Tom           5        beta
## 3 Alfonzo           7     omicron

1.6.6 Right Join

La función rigth_join(x, y, by=common_key), esta retorna todas las filas de y y las columnas de ambos (x y y). En donde no haya conincidencia el valor será NA, si hay varias coincidencias entre X y Y se incluiran todas.

us.state.areas <- as.data.frame(cbind(state.abb, state.area))
us.state.areas[1:3,]
##   state.abb state.area
## 1        AL      51609
## 2        AK     589757
## 3        AZ     113909
us.state.abbreviation.and.name <- as.data.frame(cbind(state.abb,
 state.name))
us.state.abbreviation.and.name[1:3,]
##   state.abb state.name
## 1        AL    Alabama
## 2        AK     Alaska
## 3        AZ    Arizona
us.state.abbreviation.and.name[1,1] <- "Intentional Mismatch"
us.state.with.abbreviation.and.name.and.area <- right_join(us.state.areas,
 us.state.abbreviation.and.name, by = "state.abb")
us.state.with.abbreviation.and.name.and.area[1:3,] #Alabama se reemplaza con "intentional mismatch". Como resultado, falta en la salida. Sin embargo, se incluyen todas las columnas de ambos conjuntos de datos
##   state.abb state.area state.name
## 1        AK     589757     Alaska
## 2        AZ     113909    Arizona
## 3        AR      53104   Arkansas

1.7 Slice

La función slice() proporciona una forma de incluir filas o rangos de filas específicas en sus conjuntos de datos.

msleep <- ggplot2::msleep
nrow(msleep) #inicialmente 83 filas
## [1] 83
msleep.only.first.5 <- slice(msleep, -6:-n())#Las filas 6 a 83 se eliminan. 
# La expresión “n (“) ”es el número total de filas por lo que, no es necesarios saber el numero de filas del marco de datos.
nrow(msleep.only.first.5) #Ahora solo se conservan las cinco primeras filas
## [1] 5
msleep.20.rows <- msleep %>%
 slice(20:39)
nrow(msleep.20.rows)#Ahora solo se conservan 20 filas
## [1] 20
nrow(msleep) - nrow(msleep.20.rows) #muestra la diferencia entre el marco de datos original y cortado (o tibble)
## [1] 63

1.8 Summarise

summarise() combinado con group_by (), proporciona un gran variedad de herramientas prácticas y rápidas para dimensionar datos (contar, sumar, desviación estándar y otras funciones) con una o más variables categóricas.

library(MASS)
## 
## Attaching package: 'MASS'
## The following object is masked from 'package:dplyr':
## 
##     select
data(gehan)
gehan2 <- gehan
library(tidyverse)
gehan2 %>% summarise( kount = n()) #Número de pacientes que participaron en el ensayo medico
##   kount
## 1    42
gehan2 %>%
 group_by(treat) %>%
 summarise(kount = n()) #Recuento por tratamiento/sin tratamiento
## # A tibble: 2 × 2
##   treat   kount
##   <fct>   <int>
## 1 6-MP       21
## 2 control    21
gehan2 %>%
 group_by(treat) %>%
 summarise(average.remiss.time = mean(time),
 median.remiss.time = median(time),
 std.dev.remiss.time = sd(time),
 median.abs.deviation = mad(time),
 IQR.remiss.time = IQR(time)) # Muestra las estadística generales de tratamiento / sin tratamiento
## # A tibble: 2 × 6
##   treat   average.remiss.time median.remiss.t… std.dev.remiss.… median.abs.devi…
##   <fct>                 <dbl>            <int>            <dbl>            <dbl>
## 1 6-MP                  17.1                16            10.0             10.4 
## 2 control                8.67                8             6.47             5.93
## # … with 1 more variable: IQR.remiss.time <dbl>
gehan2 %>%
 group_by(treat) %>%
 summarise(minimum.remission = min(time),
 max.remission = max(time)) #summarise() se puede utilizar para encontrar el mínimo / máximo dentro del group_by()
## # A tibble: 2 × 3
##   treat   minimum.remission max.remission
##   <fct>               <int>         <int>
## 1 6-MP                    6            35
## 2 control                 1            23

1.8.1 Summarise Across

subset.survey <- survey[1:10,]
library(dplyr)
head(subset.survey)
##      Sex Wr.Hnd NW.Hnd W.Hnd    Fold Pulse    Clap Exer Smoke Height      M.I
## 1 Female   18.5   18.0 Right  R on L    92    Left Some Never 173.00   Metric
## 2   Male   19.5   20.5  Left  R on L   104    Left None Regul 177.80 Imperial
## 3   Male   18.0   13.3 Right  L on R    87 Neither None Occas     NA     <NA>
## 4   Male   18.8   18.9 Right  R on L    NA Neither None Never 160.00   Metric
## 5   Male   20.0   20.0 Right Neither    35   Right Some Never 165.00   Metric
## 6 Female   18.0   17.7 Right  L on R    64   Right Some Never 172.72 Imperial
##      Age
## 1 18.250
## 2 17.583
## 3 16.917
## 4 20.333
## 5 23.667
## 6 21.000
subset.survey %>%
 na.omit() %>% #remove any NAs
 group_by(Sex) %>%
 summarise(across(where(is.numeric), mean,
 .names = "mean_{col}")) %>%
 head()# head () sin marco de datos especificado, usa el marco de datos o tibble que se esta trabajando en el chunk
## # A tibble: 2 × 6
##   Sex    mean_Wr.Hnd mean_NW.Hnd mean_Pulse mean_Height mean_Age
##   <fct>        <dbl>       <dbl>      <dbl>       <dbl>    <dbl>
## 1 Female        17.8        17.7       76.7        168.     25.0
## 2 Male          19.1        19.2       76.8        174.     20.3
new.sleep <- msleep %>% #Base de datos msleep
 group_by(vore, order)
(s<-summarise(new.sleep, n())) #uso summarise() para contar las combinaciones vore-order
## `summarise()` has grouped output by 'vore'. You can override using the `.groups` argument.
## # A tibble: 32 × 3
## # Groups:   vore [5]
##    vore  order           `n()`
##    <chr> <chr>           <int>
##  1 carni Carnivora          12
##  2 carni Cetacea             3
##  3 carni Cingulata           1
##  4 carni Didelphimorphia     1
##  5 carni Primates            1
##  6 carni Rodentia            1
##  7 herbi Artiodactyla        5
##  8 herbi Diprotodontia       1
##  9 herbi Hyracoidea          2
## 10 herbi Lagomorpha          1
## # … with 22 more rows
(new.sleep.totals <- msleep %>%
 group_by(vore, order) %>%
 summarise(n())) #Para obtener solo los totales de las
## `summarise()` has grouped output by 'vore'. You can override using the `.groups` argument.
## # A tibble: 32 × 3
## # Groups:   vore [5]
##    vore  order           `n()`
##    <chr> <chr>           <int>
##  1 carni Carnivora          12
##  2 carni Cetacea             3
##  3 carni Cingulata           1
##  4 carni Didelphimorphia     1
##  5 carni Primates            1
##  6 carni Rodentia            1
##  7 herbi Artiodactyla        5
##  8 herbi Diprotodontia       1
##  9 herbi Hyracoidea          2
## 10 herbi Lagomorpha          1
## # … with 22 more rows

1.9 Gathering: Convierte multiples columnas en una

La función gather() convierte varias columnas en una sola columna. Las tasas de natalidad entre adolescentes, por cada 1000 mujeres, son de www.cdc.gov

state <- c("Maryland", "Alaska", "New Jersey")
income <- c(76067,74444,73702)
median.us <- c(61372,61372,61372)
life.expectancy <- c(78.8,78.3,80.3)
teen.birth.rate.2015 <- c(17,29.3,12.1)
teen.birth.rate.2007 <- c(34.3,42.9,24.9)
teen.birth.rate.1991 <- c(54.1, 66, 41.3)
top.3.states <- data.frame(state, income, median.us,
 life.expectancy,
 teen.birth.rate.2015, teen.birth.rate.2007,
 teen.birth.rate.1991)
names(top.3.states) <- c("state", "income", "median.us",
 "life.expectancy","2015","2007","1991")
 top.3.states
##        state income median.us life.expectancy 2015 2007 1991
## 1   Maryland  76067     61372            78.8 17.0 34.3 54.1
## 2     Alaska  74444     61372            78.3 29.3 42.9 66.0
## 3 New Jersey  73702     61372            80.3 12.1 24.9 41.3
(new.top.3.states <- top.3.states %>%
 gather("2015", "2007", "1991", key = "year", value = "cases")) #Se usa gather() para recopilar los tres años en una sola columna
##        state income median.us life.expectancy year cases
## 1   Maryland  76067     61372            78.8 2015  17.0
## 2     Alaska  74444     61372            78.3 2015  29.3
## 3 New Jersey  73702     61372            80.3 2015  12.1
## 4   Maryland  76067     61372            78.8 2007  34.3
## 5     Alaska  74444     61372            78.3 2007  42.9
## 6 New Jersey  73702     61372            80.3 2007  24.9
## 7   Maryland  76067     61372            78.8 1991  54.1
## 8     Alaska  74444     61372            78.3 1991  66.0
## 9 New Jersey  73702     61372            80.3 1991  41.3

1.10 Spreading: Condensa varias filas en una

La función spread()condensa los datos de una misma observación que se encuentran en varias filas, en una sola.

(dat1 <- data.frame(Type = c("TypeA", "TypeA", "TypeB", "TypeB"), Answer = c("Yes", "No", NA, "No"), n = 1:4))
##    Type Answer n
## 1 TypeA    Yes 1
## 2 TypeA     No 2
## 3 TypeB   <NA> 3
## 4 TypeB     No 4
(dat2 <- dat1 %>%
filter(!is.na(Answer)) %>%
 spread(key=Answer, value=n)) #Después de usar spread, las respuestas "No" y "Sí" están en columnas separadas, lo que facilita los resúmenes y otros análisis
##    Type No Yes
## 1 TypeA  2   1
## 2 TypeB  4  NA

1.11 Separate: Divide una columna en múltiples columnas

La función separate() puede dividir una columna en dos o más.

#La columna teen.birth tiene tres datos por fila, separados por un carácter especial ("//").
state <- c("Maryland", "Alaska", "New Jersey")
income <- c(76067,74444,73702)
median.us <- c(61372,61372,61372)
life.expectancy <- c(78.8,78.3,80.3)
teen.birth <- c("17//34.3//54.1", "29.0//42.9//66.0", "12.1//24.9//41.3")
(top3<- data.frame(state, income, median.us,
 life.expectancy,teen.birth))
##        state income median.us life.expectancy       teen.birth
## 1   Maryland  76067     61372            78.8   17//34.3//54.1
## 2     Alaska  74444     61372            78.3 29.0//42.9//66.0
## 3 New Jersey  73702     61372            80.3 12.1//24.9//41.3
(top3.separated<- top3 %>%
 separate(teen.birth, into = c("2015", "2007","1991"), sep = "//")) # Antes de ejecutar la función separate, los años 2015, 2007 y 1991 se combinan en la columna de nacimiento de adolescentes.
##        state income median.us life.expectancy 2015 2007 1991
## 1   Maryland  76067     61372            78.8   17 34.3 54.1
## 2     Alaska  74444     61372            78.3 29.0 42.9 66.0
## 3 New Jersey  73702     61372            80.3 12.1 24.9 41.3

1.12 Resumen de las funciones útiles de DPLYR

DPLYR contiene una gran cantidad de funciones útiles para transformar los datos en lo que se necesite para resolver problemas analíticos. Los datos reales a menudo tienen valores perdidos, valores numéricamente válidos pero incorrectos, estructuras extrañas y muchas otras variaciones. El siguiente conjunto de herramientas se pueden utilizar junto con las cinco funciones clave de DPLYR o, en algunos casos, de forma independiente. El manual DPLYR tiene mas información de interes.

1.12.1 Número de observaciones (n) usado en varias funciones de DPLYR

La función n() se encarga de hacer recuentos de datos. Esta función se aplica para funciones como mutate(), summarise() y filter().

1.12.2 Conteos básicos

m <- mutate(new.sleep, kount = n()) # Nueva variable, kount agregado en el extremo derecho
m[1:5,c(1:4,10:12)] #Se limita el numero de columnas para que se puedan ver en la página
## # A tibble: 5 × 7
## # Groups:   vore, order [5]
##   name                       genus      vore  order        brainwt  bodywt kount
##   <chr>                      <chr>      <chr> <chr>          <dbl>   <dbl> <int>
## 1 Cheetah                    Acinonyx   carni Carnivora   NA        50        12
## 2 Owl monkey                 Aotus      omni  Primates     0.0155    0.48     10
## 3 Mountain beaver            Aplodontia herbi Rodentia    NA         1.35     16
## 4 Greater short-tailed shrew Blarina    omni  Soricomorp…  0.00029   0.019     3
## 5 Cow                        Bos        herbi Artiodacty…  0.423   600         5
f <- filter(new.sleep, n() > 14)#Filtrar por recuento de pedidos superiores a 14
f[1:5,c(1:4,10:11)] 
## # A tibble: 5 × 6
## # Groups:   vore, order [1]
##   name                      genus      vore  order    brainwt bodywt
##   <chr>                     <chr>      <chr> <chr>      <dbl>  <dbl>
## 1 Mountain beaver           Aplodontia herbi Rodentia NA       1.35 
## 2 Guinea pig                Cavis      herbi Rodentia  0.0055  0.728
## 3 Chinchilla                Chinchilla herbi Rodentia  0.0064  0.42 
## 4 Western american chipmunk Eutamias   herbi Rodentia NA       0.071
## 5 Mongolian gerbil          Meriones   herbi Rodentia NA       0.053

Funciones Nth

#Ingresar primero estos datos
salary.description <- c("Golden parachute type","Well to do",
"Average","Below average", "bring date seeds instead of flowers")
first(salary.description)
## [1] "Golden parachute type"
#Despúes ingresar
last(salary.description)
## [1] "bring date seeds instead of flowers"
#Tercera observación desde el final
nth(salary.description, -3)
## [1] "Average"
#Segundo elemento del vector
nth(salary.description,2)
## [1] "Well to do"

1.12.4 Contar distintos valores

La función n_distinct() determina cuantos valores unicos hay en un vector.

a.vector <- c(22,33,44,1,2,3,3,3,4)
(original.length <- length(a.vector)) #Tiene encuenta todos los datos del vector, incluso los que se repiten
## [1] 9
(distinct.a.vector <- n_distinct(a.vector)) #Muestra el total de valores del vector sin tener en cuenta las repeticiones que haya de algun dato
## [1] 7
(test1 <- if_else(original.length == distinct.a.vector, "all values unique","some duplicate values in vector")) #Si se repite algun valor mostrara un mensaje que lo indique
## [1] "some duplicate values in vector"
b.vector <- c(1,2,3,4,5,6)
length(b.vector)
## [1] 6
(distinct.b.vector <- n_distinct(b.vector))#Muestra el recuento (total) de números distintos
## [1] 6
(test2 <- if_else(length(b.vector) == distinct.b.vector, "all values unique", "duplicates")) #Si hay valores unicos mostrara un mensaje que lo indique
## [1] "all values unique"

1.12.5 na_if

La función na_if() puede establecer un valor de cálculo en un procedimiento indeterminado, especificando “NA”

test <- c(100, 0, 999)
(x <- 5000/test) #Dividir entre 0 es una operación indetermina que tiende al infinito
## [1] 50.000000       Inf  5.005005
#En lugar de tener un valor de infinito en el vector resultante, puede programarse en R para que sustituya el "Inf" por "NA" 
(x1 <- 5000/na_if(test,0))
## [1] 50.000000        NA  5.005005
class(x)
## [1] "numeric"

1.12.6 Coalesce para reemplazar un valor perdido

La función coalesce() reemplaza los valores perdidos de un vector con cero o algún otro valor.

(y <- c(33,4,11,NA,9)) #antes de reemplazar los NA
## [1] 33  4 11 NA  9
 (y<- coalesce(y,0)) #reemplazando los valores con la función coalesce
## [1] 33  4 11  0  9

1.13 Funciones de rango

1.13.1 Rangos por indices

w <- c(100,4,12,6,8,3)
(rank1 <-row_number(y))
## [1] 5 2 4 1 3
w[rank1[1]] #me muestra el número más pequeño
## [1] 8
w[rank1[6]] #me muestra el número más grande
## [1] NA

1.13.2 Rango mínimo

(rank2 <- min_rank(w)) 
## [1] 6 2 5 3 4 1

1.13.3 Dense Rank

(rank3 <- dense_rank(w))
## [1] 6 2 5 3 4 1

1.13.4 Porcent Rank

(rank4 <- percent_rank(w)) #El primer elemento de "y" está en el percentil 100
## [1] 1.0 0.2 0.8 0.4 0.6 0.0
#el segundo elemento de "y" está en el percentil 
#el último elemento de "y" está en el percentil 0:

1.13.5 Función de distribución acumulada

La función cume_dist() muestra la proporción de todos los valores menores o iguales al rango actual

(rank5 <- cume_dist(w))
## [1] 1.0000000 0.3333333 0.8333333 0.5000000 0.6666667 0.1666667
(rank6 = ntile(w, 3)) #Se divide el vector de entrada en 3 depositos
## [1] 3 1 3 2 2 1
test.vector <- c(2,22,33,44,77,89,99)
quantile(test.vector, prob = seq(0,1,length = 11),type = 5) #La función quantile() de R tiene una salida fácil de leer
##   0%  10%  20%  30%  40%  50%  60%  70%  80%  90% 100% 
##  2.0  6.0 20.0 28.6 36.3 44.0 67.1 81.8 90.0 97.0 99.0

1.14 Sampling

Cuando los grupos de datos son muy grandes es dificíl manejarlos y se requiere de un muestreo o resumen intermedio de los datos.

data("ChickWeight")
(my.sample <- sample_n(ChickWeight, 5)) #se escoge al azar 5 filas del grupo de datos ChickWeight
##   weight Time Chick Diet
## 1     48    4     5    1
## 2    151   18    30    2
## 3    164   14     5    1
## 4    175   21    23    2
## 5     41    0     6    1

NOTA: Se debe establecer un número de semilla cada vez que desee una muestra para que otros puedan reproducir el procedimiento. De lo contrario, cada vez que se ejecuta la rutina, se pueden obtener resultados diferentes.

set.seed(833)

Muestrear con replace = TRUE significa que puede obtener la misma fila o elemento más de una vez. Su elección de True o False para el reemplazo depende de su propósito. Si, por ejemplo, está investigando defectos de fabricación, es posible que desee utilizar replace = FALSE, ya que no quiere perder el tiempo investigando el mismo defecto de nuevo.

(mysample <- sample_n(ChickWeight, 10, replace = TRUE))
##    weight Time Chick Diet
## 1      98    8    45    4
## 2      42    0    17    1
## 3      98    8    36    3
## 4      51    2    11    1
## 5     198   20     3    1
## 6     237   21    49    4
## 7     205   16    50    4
## 8     170   16    39    3
## 9     332   18    35    3
## 10    144   14    33    3
mysample1 <- sample_n(mtcars, 12, weight = cyl)
mysample1[,1:5] #En este ejemplo es más probable que los automóviles con más cilindros se seleccionen como parte de la muestra
##                     mpg cyl  disp  hp drat
## AMC Javelin        15.2   8 304.0 150 3.15
## Porsche 914-2      26.0   4 120.3  91 4.43
## Merc 280           19.2   6 167.6 123 3.92
## Cadillac Fleetwood 10.4   8 472.0 205 2.93
## Merc 240D          24.4   4 146.7  62 3.69
## Datsun 710         22.8   4 108.0  93 3.85
## Merc 280C          17.8   6 167.6 123 3.92
## Mazda RX4 Wag      21.0   6 160.0 110 3.90
## Merc 450SLC        15.2   8 275.8 180 3.07
## Chrysler Imperial  14.7   8 440.0 230 3.23
## Maserati Bora      15.0   8 301.0 335 3.54
## Valiant            18.1   6 225.0 105 2.76

Se utiliza la función sample_frac() para obtener una muestra igual a un porcentaje específico de las filas del marco de datos

(t12 <- sample_frac(ChickWeight, 0.02))
##    weight Time Chick Diet
## 1      48    2    13    1
## 2      62    6    12    1
## 3     197   20    45    4
## 4     234   18    42    4
## 5      58    4    28    2
## 6     163   16     3    1
## 7     103    8    41    4
## 8     103    8    42    4
## 9     120   18    19    1
## 10     48    2    36    3
## 11     80    6    48    4
## 12    137   12    33    3
by_hair_color <- starwars %>% group_by(hair_color) #group_by () identifica a los personajes de Starwars por grupo de cabello, y luego se selecciona el 7% de los registros en cada grupo. Esto es útil cuando desea un porcentaje establecido de grupos cuyos tamaños varían
otrosam <- sample_frac(by_hair_color, .07, replace = TRUE)
otrosam[,1:5]
## # A tibble: 5 × 5
## # Groups:   hair_color [3]
##   name       height  mass hair_color skin_color      
##   <chr>       <int> <dbl> <chr>      <chr>           
## 1 Eeth Koth     171    NA black      brown           
## 2 Dormé         165    NA brown      light           
## 3 Sebulba       112    40 none       grey, red       
## 4 Shaak Ti      178    57 none       red, blue, white
## 5 Tion Medon    206    80 none       grey
(row.kount.only <- ChickWeight %>% tally()) #La función tally() proporciona recuentos del total de los datos
##     n
## 1 578
(diet.kount <- ChickWeight %>% count(Diet)) #La función count() proporcionan recuentos por grupo de datos. 
##   Diet   n
## 1    1 220
## 2    2 120
## 3    3 120
## 4    4 118

1.15 Diversas funciones de DPLYR

1.15.1 add_count para filtros grupales

especies_unic <- starwars %>%
 add_count(species) %>% #add_count() es util para el filtrado grupal de datos
 filter(n == 1)
especies_unic[,1:6]
## # A tibble: 29 × 6
##    name                  height  mass hair_color skin_color       eye_color
##    <chr>                  <int> <dbl> <chr>      <chr>            <chr>    
##  1 Greedo                   173    74 <NA>       green            black    
##  2 Jabba Desilijic Tiure    175  1358 <NA>       green-tan, brown orange   
##  3 Yoda                      66    17 white      green            brown    
##  4 Bossk                    190   113 none       green            red      
##  5 Ackbar                   180    83 none       brown mottle     orange   
##  6 Wicket Systri Warrick     88    20 brown      brown            brown    
##  7 Nien Nunb                160    68 none       grey             black    
##  8 Nute Gunray              191    90 none       mottled green    red      
##  9 Watto                    137    NA black      blue, grey       yellow   
## 10 Sebulba                  112    40 none       grey, red        orange   
## # … with 19 more rows

1.15.2 Rename

data(mtcars)
names(mtcars)
##  [1] "mpg"  "cyl"  "disp" "hp"   "drat" "wt"   "qsec" "vs"   "am"   "gear"
## [11] "carb"
mtcars <- rename(mtcars, spam_mpg = mpg)
names(mtcars)
##  [1] "spam_mpg" "cyl"      "disp"     "hp"       "drat"     "wt"      
##  [7] "qsec"     "vs"       "am"       "gear"     "carb"

1.15.3 case_when

La función case_when() es particularmente útil dentro de la función mutate(). Esta puede crear una nueva variable que se base en una combinación compleja de variables existentes.

data(starwars)
(new.starwars <- starwars %>%
 dplyr::select(name, mass, gender, species, height) %>%
 mutate(type = case_when(height > 200 | mass > 200 ~ "large",
 species == "Droid" ~ "robot", TRUE ~ "other")))
## # A tibble: 87 × 6
##    name                mass gender    species height type 
##    <chr>              <dbl> <chr>     <chr>    <int> <chr>
##  1 Luke Skywalker        77 masculine Human      172 other
##  2 C-3PO                 75 masculine Droid      167 robot
##  3 R2-D2                 32 masculine Droid       96 robot
##  4 Darth Vader          136 masculine Human      202 large
##  5 Leia Organa           49 feminine  Human      150 other
##  6 Owen Lars            120 masculine Human      178 other
##  7 Beru Whitesun lars    75 feminine  Human      165 other
##  8 R5-D4                 32 masculine Droid       97 robot
##  9 Biggs Darklighter     84 masculine Human      183 other
## 10 Obi-Wan Kenobi        77 masculine Human      182 other
## # … with 77 more rows

Nota importante A veces, los paquetes R tienen funciones con el mismo nombre que provocan una confusión. Tanto MASS como DPLYR tienen la misma función, “select”. Para asegurarse de que se utiliza el paquete DPLYR, utilice dplyr :: select como función. Esa sintaxis obliga a R a usar DPLYR en lugar de la versión MASS de select