Manipulacion de data frames condplyr

 

Introducción


Ya hemos visto que la estructura de datos más importante en R es el data frame. Esta estructura permite representar la información en forma de tabular y trabajar con ella en una forma fácil de comprender. La idea detrás de un data frame es que cada fila represente una observación y cada columna represente una variable (medición, propiedad, característica, etc). El porqué de esto lo veremos en un próximo post. De momento quedémonos con esta idea.

Por ejemplo, en el dataset iris vemos que cada fila representa una  observación sobre una flor, mientras que cada columna representa una variable de la flor observada.

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

 

Dada la importancia de trabajar con data frames, es importante conocer las herramientas con que contamos para manipularlos. Ya hemos visto en el post sobre subsetting un poco sobre como extraer partes de un data frame o realizar modificaciones utilizando los operadores [ y $. No obstante, otras operaciones más complejas como realizar agrupaciones u ordenar en función de los valores de una columna pueden resultar tareas tediosas. Es debido a esto que fue desarrollado el paquete dplyr, el cual provee funciones que facilitan enormemente las tareas usuales con que nos vamos a topar al momento de trabajar con data frames.

 

El paquete dplyr


El paquete dplyr fue desarrollado por Hadley Wickham (RStudio) como una optimización del paquete plyr. Este paquete no provee ninguna funcionalidad que no pueda ser realizada con las funciones del paquete base, sino que su valor agregado está en la simplicidad que provee para realizar tales operaciones. A su vez, dado que el paquete está escrito en C++, las funciones que provee permiten hacer operaciones más rápido que su equivalente del paquete base.

Las funciones principales que provee el paquete dplyr son:

  • select: devuelve solo las columnas indicadas de un dataframe.
  • filter: permite filtrar filas de una data frame según una expresión lógica.
  • arrange: ordena las filas de un data frame en función de los valores de una o más columnas.
  • rename: permite cambiar el nombre de una columna.
  • mutate: permite agregar una nueva columna o transformar una existente.
  • summarise: permite realizar resúmenes estadísticos de variables en un data frame.

 

Todas estas funciones tiene la particularidad de que su primer argumento es el data frame al que le realizará la operación, mientras que los subsiguiente argumentos describen como realizar tal operación. Finalmente el resultado de todas estas funciones es un nuevo data frame.

Luego, otra función/operador que nos provee este paquete es el pipe (%>%). Este operador es usado para conectar la salida de una función con la entrada de la siguiente. Esto es muy útil dado que, como mencionamos, todas estas funciones tienen como entrada un data frame, y como salida otro data frame por lo que el pipe nos permite encadenarlas, y así mejorar la legibilidad del código. Más adelante lo veremos en acción.

Antes de comenzar a ver las funciones debemos instalar el paquete y cargarlo:

install.packages("dplyr")
...

library(dplyr)
Attaching package: ‘dplyr’

The following objects are masked from ‘package:stats’:

 filter, lag

The following objects are masked from ‘package:base’:

 intersect, setdiff, setequal, union

El mensaje que aparece al cargarse el paquete (The following objects are masked from) nos indica que el paquete cargado, en este caso dplyr, tiene funciones que poseen el mismo nombre que otro paquete cargado previamente. De este modo, cuando llamemos a una función cuyo nombre está presente en más de un paquete, se entenderá que hacemos referencia a la del último paquete cargado. Si queremos utilizar una función que quedó enmascarada debemos indicar el nombre del paquete al que pertenece de la siguiente forma:

paquete::función()

 

Funciones


Para los ejemplos en esta sección utilizaremos los datasets mtcars e iris.

head(mtcars)
                   mpg cyl disp  hp drat    wt  qsec vs am gear carb
Mazda RX4         21.0   6  160 110 3.90 2.620 16.46  0  1    4    4
Mazda RX4 Wag     21.0   6  160 110 3.90 2.875 17.02  0  1    4    4
Datsun 710        22.8   4  108  93 3.85 2.320 18.61  1  1    4    1
Hornet 4 Drive    21.4   6  258 110 3.08 3.215 19.44  1  0    3    1
Hornet Sportabout 18.7   8  360 175 3.15 3.440 17.02  0  0    3    2
Valiant           18.1   6  225 105 2.76 3.460 20.22  1  0    3    1

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

 

select

La función select es usada para seleccionar columnas de un data frame que queremos extraer. Por ejemplo, en el caso del dataset mtcars tenemos 11 columnas, pero solo vamos a trabajar con algunas de ellas. Entonces mediante select podemos indicar cuales columnas seleccionar, teniendo la posibilidad de hacerlo tanto mediante sus indices como mediante su nombres.

head( select(mtcars, 1, 3) )
                   mpg disp
Mazda RX4         21.0  160
Mazda RX4 Wag     21.0  160
Datsun 710        22.8  108
Hornet 4 Drive    21.4  258
Hornet Sportabout 18.7  360
Valiant           18.1  225

head( select(mtcars, mpg, disp) )
                   mpg disp
Mazda RX4         21.0  160
Mazda RX4 Wag     21.0  160
Datsun 710        22.8  108
Hornet 4 Drive    21.4  258
Hornet Sportabout 18.7  360
Valiant           18.1  225

En este ejemplo, hemos extraído las columnas mpg (1) y disp (3). Ambas expresiones son equivalentes. La función head simplemente la utilizamos para imprimir en pantalla solo 6 filas del dataset resultante.

Por otra parte, la función select permite utilizar diferentes funciones de ayuda (?select_helpers) para indicar las columnas a extraer:

"-": selecciona todas las columnas menos las indicadas.

head( select(mtcars, -c(mpg, disp)) )
                  cyl  hp drat    wt  qsec vs am gear carb
Mazda RX4           6 110 3.90 2.620 16.46  0  1    4    4
Mazda RX4 Wag       6 110 3.90 2.875 17.02  0  1    4    4
Datsun 710          4  93 3.85 2.320 18.61  1  1    4    1
Hornet 4 Drive      6 110 3.08 3.215 19.44  1  0    3    1
Hornet Sportabout   8 175 3.15 3.440 17.02  0  0    3    2
Valiant             6 105 2.76 3.460 20.22  1  0    3    1

 

":": selecciona un rango de columnas.

head( select(mtcars, 1:3) ) # Tambien podríamos haber usado mpg:disp
                   mpg cyl disp
Mazda RX4         21.0   6  160
Mazda RX4 Wag     21.0   6  160
Datsun 710        22.8   4  108
Hornet 4 Drive    21.4   6  258
Hornet Sportabout 18.7   8  360
Valiant           18.1   6  225

 

starts_with: selecciona todas las columnas que comiencen con el patrón indicado.

head( select(iris, starts_with("Petal")))
  Petal.Length Petal.Width
1          1.4         0.2
2          1.4         0.2
3          1.3         0.2
4          1.5         0.2
5          1.4         0.2
6          1.7         0.4

 

ends_with: selecciona todas las columnas que terminen con el patrón indicado.

head( select(iris, ends_with("Width")))
  Sepal.Width Petal.Width
1         3.5         0.2
2         3.0         0.2
3         3.2         0.2
4         3.1         0.2
5         3.6         0.2
6         3.9         0.4

 

contains: selecciona las columnas que posean el patrón indicado.

head( select(iris, contains("etal")))
  Petal.Length Petal.Width
1          1.4         0.2
2          1.4         0.2
3          1.3         0.2
4          1.5         0.2
5          1.4         0.2
6          1.7         0.4

 

matches: similar a contains, pero permite poner una expresión regular.

head( select(iris, matches(".t.")))
  Sepal.Length Sepal.Width Petal.Length Petal.Width
1          5.1         3.5          1.4         0.2
2          4.9         3.0          1.4         0.2
3          4.7         3.2          1.3         0.2
4          4.6         3.1          1.5         0.2
5          5.0         3.6          1.4         0.2
6          5.4         3.9          1.7         0.4

 

everything: completa con las columnas del data frame no pasadas como argumento. De esta forma se nos simplifican tareas de reordenar las columnas, poniendo primeras las que nos interesen destacar.

head( select(iris, Species, everything()))
  Species Sepal.Length Sepal.Width Petal.Length Petal.Width
1  setosa          5.1         3.5          1.4         0.2
2  setosa          4.9         3.0          1.4         0.2
3  setosa          4.7         3.2          1.3         0.2
4  setosa          4.6         3.1          1.5         0.2
5  setosa          5.0         3.6          1.4         0.2
6  setosa          5.4         3.9          1.7         0.4

 

one_of: selecciona las variables pasadas en un vector.

vars <- c("Petal.Length", "Petal.Width")

head( select(iris, one_of(vars)))
  Petal.Length Petal.Width
1          1.4         0.2
2          1.4         0.2
3          1.3         0.2
4          1.5         0.2
5          1.4         0.2
6          1.7         0.4

 

filter

Así como la función select es utilizada para seleccionar columnas, la función filter hace lo propio con las filas del data frame. Supongamos que queremos extraer los automóviles del dataset mtcars que poseen 4 cilindros y más de 100 hp de potencia. Entonces haríamos:

filter(mtcars, cyl == 4 & hp > 100)
   mpg cyl  disp  hp drat    wt qsec vs am gear carb
1 30.4   4  95.1 113 3.77 1.513 16.9  1  1    5    2
2 21.4   4 121.0 109 4.11 2.780 18.6  1  1    4    2

 

La expresión lógica de la función filter podemos hacer que sea tan compleja como necesitemos. Hay que recordar que las para indicar múltiples condiciones utilizamos & (and), mientras que para indicar que conserve las filas que cumplen al menos un criterio usamos | (or).

 

arrange

La función arrange es usada para reordenar las filas de una data frame según una o más columnas. Por ejemplo, si queremos reordenar mtcars de acorde a la variable mpg haríamos los siguiente:

arrange(mtcars, mpg)

   mpg cyl disp  hp drat    wt  qsec vs am gear carb
1 10.4   8  472 205 2.93 5.250 17.98  0  0    3    4
2 10.4   8  460 215 3.00 5.424 17.82  0  0    3    4
3 13.3   8  350 245 3.73 3.840 15.41  0  0    3    4
4 14.3   8  360 245 3.21 3.570 15.84  0  0    3    4
5 14.7   8  440 230 3.23 5.345 17.42  0  0    3    4
6 15.0   8  301 335 3.54 3.570 14.60  0  1    5    8

...

27 26.0   4 120.3  91 4.43 2.140 16.70  0  1    5    2
28 27.3   4  79.0  66 4.08 1.935 18.90  1  1    4    1
29 30.4   4  75.7  52 4.93 1.615 18.52  1  1    4    2
30 30.4   4  95.1 113 3.77 1.513 16.90  1  1    5    2
31 32.4   4  78.7  66 4.08 2.200 19.47  1  1    4    1
32 33.9   4  71.1  65 4.22 1.835 19.90  1  1    4    1

 

Vemos que se ha ordenado de menor a mayor. Si queremos ordenar al revés (primero los valores más grandes) tenemos que poner desc(mpg) como argumento. Por otro lado, si queremos emplear múltiples condiciones de ordenamiento debemos poner tales condiciones en orden dentro de los argumentos de filter. Por ejemplo, con arrange(mtcars, hp, desc(mpg)) haríamos que se ordene primero por la columna hp en orden ascendente, y luego por mpg en forma descendente.

 

rename

La función rename permite modificar el nombre de una columna, conservando el resto de columnas.

head( rename(iris, petal_length = Petal.Length) )
  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

 

La función select permite realizar también una modificación en los nombre de las columnas, pero en ese caso solo se conservan las columnas seleccionadas.

head( select(iris, petal_length = Petal.Length) )
  petal_length
1          1.4
2          1.4
3          1.3
4          1.5
5          1.4
6          1.7

 

mutate

La función mutate tiene la finalidad de realizar transformaciones sobre variables (columnas) en un data frame. Supongamos que en mtcars queremos convertir la variable hp (Horse Power) a cv (caballos de vapor). Hasta el momento lo que hubiésemos hecho es:

mtcars$cv <- mtcars$hp * 0.9863

Esta forma es perfectamente valida, pero si estamos usando las funciones del paquete dplyr, lo que aporta más legibilidad al código es seguir usando la misma familia de funciones. Esto lo ampliaremos más adelante cuando veamos el pipe. Entonces:

head( mutate(mtcars, cv = hp * 0.9863) )
   mpg cyl disp  hp drat    wt  qsec vs am gear carb       cv
1 21.0   6  160 110 3.90 2.620 16.46  0  1    4    4 108.4930
2 21.0   6  160 110 3.90 2.875 17.02  0  1    4    4 108.4930
3 22.8   4  108  93 3.85 2.320 18.61  1  1    4    1  91.7259
4 21.4   6  258 110 3.08 3.215 19.44  1  0    3    1 108.4930
5 18.7   8  360 175 3.15 3.440 17.02  0  0    3    2 172.6025
6 18.1   6  225 105 2.76 3.460 20.22  1  0    3    1 103.5615

Otros ejemplo podría ser estandarizar una variable. Para esto tomemos la variable mpg, le restamos su media y la dividimos por su desvío estándar.

head( mutate(mtcars, mpg_est = (mpg - mean(mpg)) / sd(mpg) ))
   mpg cyl disp  hp drat    wt  qsec vs am gear carb    mpg_est
1 21.0   6  160 110 3.90 2.620 16.46  0  1    4    4  0.1508848
2 21.0   6  160 110 3.90 2.875 17.02  0  1    4    4  0.1508848
3 22.8   4  108  93 3.85 2.320 18.61  1  1    4    1  0.4495434
4 21.4   6  258 110 3.08 3.215 19.44  1  0    3    1  0.2172534
5 18.7   8  360 175 3.15 3.440 17.02  0  0    3    2 -0.2307345
6 18.1   6  225 105 2.76 3.460 20.22  1  0    3    1 -0.3302874

 

group_by y summarize

La función group_by es usada para agrupar datos según una variable. Una vez con los datos agrupados podemos summarize para resumir estos utilizando una función de agregación. Para los que tengan conocimiento de SQL, estos conceptos son idénticos a los empleado en ese lenguaje.

Por ejemplo, en el dataset mtcars podríamos querer saber cual es el valor medio de mpg y hp para los vehículos acorde a su cantidad de cilindros. Entonces agrupamos los vehículos por la variable cyl y tomamos la media de mpg y hp.

by_cyl <- group_by(mtcars, cyl)
summarise(by_cyl, mean(mpg), mean(hp))
# A tibble: 3 × 3
    cyl `mean(mpg)` `mean(hp)`
               
1     4    26.66364   82.63636
2     6    19.74286  122.28571
3     8    15.10000  209.21429

Lo que hemos hecho es tomar todos los vehículos con 4 cilindros y calcular la media de mpg y hp para estos. Luego hemos hecho lo propio con los vehículos de 6 y 8 cilindros. Finalmente se plasma en la tabla resultante estos valores.

Algunas de las funciones de agregación que se pueden emplear son:

  • n():     cantidad de elementos
  • sum():   suma
  • mean():  promedio
  • sd():    desvío estándar.

En general se puede utilizar cualquier función que cumpla con que lo datos de entrada sean numericos y como salida se entregue una constante (vector de longitud 1).

 

pipe

El pipe (%>%) es un operador que permite encadenas funciones. Lo que hace es tomar la salida de una función y pasarla como entrada de la siguiente función. Esto ayuda enormemente a mejorar la legibilidad del código.

Por ejemplo, si queremos tomar el promedio de mpg y hp para vehículos de 6 y 8 cilindros y peso (wt) superior a 3K lbs, con lo que vimos hasta acá deberíamos hacer algo así:

mtcars_aux <- select(mtcars, mpg, hp, cyl, wt)
mtcars_aux <- filter(mtcars_aux, cyl != 4 & wt > 3.000)
mtcars_aux <- group_by(mtcars_aux, cyl)
mtcars_aux <- summarize(mtcars_aux, mean(hp), mean(mpg))
mtcars_aux

En cambio, utilizando el pipe podemos encadenar las operaciones:

mtcars %>% 
  select(mpg, hp, cyl, wt) %>% 
  filter(cyl != 4 & wt > 3.000) %>% 
  group_by(cyl) %>% 
  summarize(mean(hp), mean(mpg))

# A tibble: 2 × 3
 cyl `mean(hp)` `mean(mpg)`
 <dbl> <dbl> <dbl>
1 6 115.2500 19.125
2 8 209.2143 15.100

En este caso estamos tomando el dataset y lo pasamos a la función select. Luego de elegir las columnas con que trabajaremos enviamos el dataset resultante a la función filter, y así sucesivamente hasta obtener el resultado final.

 

 

Comentarios

47 Comments

  1. Abraham

    Hola Mauricio. Muy buena página y muy buenas explicaciones.

    Espero que aún en estas fechas leas los comentarios y dudas.. Y quizá me puedas ayudar en una duda que no logro resolver:

    – Tengo un data frame con nombres de filas y nombres de columna y quiero que, al seleccionar un dato determinado, pueda extraer a que fila y a que columna corresponde, por ejemplo:

    Enero Febrero Marzo

    2000 18 22 20
    2001 12 12 14
    2002 14 12 16
    2003 18 10 16

    Y que al seleccionar, por ejemplo, el dato que corresponde a 22 me muestre que pertenece a la columna llamada «Febrero» de la fila llamada «2000»…

    De antemano muchas gracias….

    Reply
    • Abraham

      El ejemplo del data frame se ha desacomodado por el navegador, pero se supone que trate de poner que los nombres de columna son «Enero», «Febrero», «Marzo» y que los nombres de fila son «2000», «2001», «2002», «2003»…

      Reply
  2. Dulce

    Hola Mauricio, soy nueva usando R. Y necesito filtrar un dataframe, utilizando una columna en la que comience que me quede únicamente con las filas en la que esa columna comienza con el prefijo «SNLU» ¿podrías ayudarme, por favor?

    Mil gracias

    Reply
    • jaal

      Hola Dulce , debes usar la función start_with() dentro de la funcion Select, algo así:

      select(tu_dataframe, start_with(«SNLU»))

      Reply
  3. Alex

    Hola Maurocio, muchas gracias por la información pero estoy un poco atascado para lo que quiero hacer… resulta que tengo un dataset con 5040 elementos y necesito guardar en 5 variables diferentes 1008 elementos del dataset original indiscriminadamente, alguna idea de como lograrlo? hay alguna función que me permita seleccionar n elementos de un dataset? gracias de antemano!

    Reply
    • Alex x2

      Acabo de encontrar la respuesta en otra entrada del blog en «Selección de Filas y Columnas» jajaj tremendo material tienes aquí Mauricio, muchas gracias!!

      Reply
  4. ROGER ALEJANDRO MANTILLA VARELA

    Hola! Cómo podría crear una nueva variable bajo condiciones de otras variables ya existentes en la data, por ejemplo una nueva variable que cumpla que la edad sea menor a un parámetro y que se encuentre en una ciudad en específico, si es así, se le asigne el valor de 1, caso contrario 0

    Reply
    • Jesus

      Seviría la funciòn mutate con un ifelse en la creación de la nueva columna.

      Reply
  5. MariaJosé

    hola! necesito un sos y he visto la buena voluntad de Mauricio.
    Tengo un data frame con una columna que me indica si un persona aprobó o reprobó el curso… necesito agrupar ese DF por curso y saber el % de Aprobación que tuvo ¿como calculo eso? le he dado mil vueltas y no logro imaginarlo, si me pueden ayudar porfavor!!!!

    Reply
  6. Milagros Delgado Valencia

    Estimados por favor necesito su ayuda
    Soy nueva en R y quisiera dividir dos columnas, quiero sacar el ticket promedio por persona.
    Tengo la columna ingreso total por persona y quiero dividir entre el total de tickets por persona y asi sacar otra columna donde se haga esa operacion.
    Deberia dividir Ingresos total/ticket por persona. Pero como lo hago en R?

    Espero me puedan ayudar

    Muchas gracias desde ya

    Reply
  7. Marcos

    GENIAL! Es un gran tutorial.
    Deberias publicar un libro con todo esto.
    Gracias

    Reply
  8. Alfredo

    Excelente. Muy sencillo de entender

    Reply
  9. Antonio

    Estimados, muchas gracias por toda la información, soy nuevo utilizando R y quiero pedirles ayuda para realizar una búsqueda por valor aproximado en una variable string, necesito buscar si un dato de una columna de un data.frame está contenido en el valor de otra columna de otro data.frame, ¿pueden ayudarme?

    Reply
  10. alejandra

    Hola Mauricio, muchas gracias por el blog me a ayudado mucho, pero tengo el siguiente problema necesito saber la cantidad de repeticiones que hay de una variable y después de eso quedarme con todos los datos que se repiten para trabajarlos y en mi caso solo puedo contar pero no sé como llamar los datos que se repiten… de antemano muchas gracias.

    Reply
  11. Maria

    Hola tengo un problema con dataframe donde hay inconsistencia de datos y en campo edad tengo la edad(de los socios), en campo antiguedad(la antiguedad de ellos) y hay fallos y debo modificar con R pues los datos vienen mal y poner cuando sea menor de 18 la resta de edad-antiguedad<18 poner edad-18, pues ningun socios entro con menos de 18, si es mayor esta bien el dato es la antiguedad
    ^SI(edad-antiguedad<18;edad-18;antiguedad) asi seria en excel
    En R

    with(datos$antiguedad = function(anterronea)#datos es el data frame
    {
    if(datos$INCAGESEN <18 1){#INCAGESEN=eda-antiguedad
    datos$edad- 18)
    } else
    {
    datos$antiguedad
    }
    )

    No se hacer el cambio alguna ayuda porfa.
    NOse usar bien el IF en un datframe

    Reply
  12. Ram

    Hola, genial el post, pero cómo hago para calcular el porcentaje de missing de todas las columnas?

    gracias

    Reply
  13. Max

    Muy bueno el blog, me sirvio mucho para lo que estaba buscando ..

    Reply
  14. Hector Juan

    GRACIAS MAURICIO POR TU PROGRAMA ME SIENTO BIEN AGRADECIDO Y ES MUY UTIL.

    Reply
  15. Hector Juan

    Bueno me ha resultado excelente gracias mauricio

    Reply
  16. Borja

    Buenas tardes!

    Concuerdo con los otros comentarios. Muy bien explicado todo, por eso quiero preguntar el problema que tengo, soy incapaz de hacerlo sin que me consuma una barbaridad de tiempo de procesamiento, por lo que estoy seguro de que se podría hacer de otra forma mucho más rápida. Me explico:

    Tengo una estructura de datos (AB) tal que:

    id grupo valor_1 valor_2
    1 1 a 8 3
    2 2 a 65 24
    3 3 b 9 15
    4 4 a 11 15
    5 5 b 89 34
    6 6 a 3 2
    7 7 a 28 13
    8 8 b 152 75
    . . . . .
    . . . . .
    . . . . .

    y usando la función «filter», selecciono todos los «b», y los guardo en otra nueva estructura de datos llamada «B», quedando tal que:

    id grupo valor_1 valor_2
    1 3 b 9 15
    2 5 b 89 34
    3 8 b 152 75
    . . . . .
    . . . . .
    . . . . .

    Pues bien, con esta nueva estructura de datos «B», hago regresión lineal con la función «lm», generando la variable «pred»:

    pred<-lm(formula=valor_2~valor_1,data="B",na.action=na.exclude)

    Después utilizo "predict.lm" para volver a calcular los valores de la variable "valor_2", y los asigno a una nueva estructura de datos llamada "C":

    C<-predict.lm(pred,B)

    View(C)

    id grupo valor_1 valor_pred
    1 3 b 9 22
    2 5 b 89 37
    3 8 b 152 89
    . . . . .
    . . . . .
    . . . . .

    Mí objetivo, es volver a poner en el orden adecuado, y en una nueva estructura de datos "D", los nuevos datos que he obtenido en la estructura de datos "C", a partir de un array con longitud similar a "AB", una columna y todo NAs, quedando tal que:

    valor_2
    1 NA
    2 NA
    3 22*
    4 NA
    5 37*
    6 NA
    7 NA
    8 89*
    . . . . .
    . . . . .
    . . . . .

    * posición en la que se encontraba el valor predicho de "B"

    Lo he logrado hacer con lo siguiente:

    # n es el número de filas de "AB" y n_aux es el número de filas de "B"

    for (i_1 in 1:n_aux) {
    for (i in 1:n) {
    if (C[i1,1]==i) {
    D[i]<-C[i_1,2]
    }
    }
    }

    El problema que tengo, es que son cientos de miles de filas, y a ojo, el cálculo para una sola columna, tardaría unas cuantas horas, y algo me dice que se podría hacer en muchísimo menos tiempo….¿alguien sabría cómo hacerlo para no tener que hacer un bucle que tarde tantísimo tiempo?

    Primero probé con la función "subset", que se incluye en "lm", pero no me seleccionaba y analizaba los datos objetivo (la estaré usando mal)…

    Espero haberme explicado bien.

    Muchas gracias por adelantado!

    Reply
    • Borja

      :'( nadie me contesta….

      Reply
      • Isabel

        Hola Borja, no sé si es demasiado tarde…

        Lo primero que se me ocurre es que en la tabla C te quedes solo con el grupo (b) y con el valor predicho, y a continuación sobre AB haz un left_join con el by = «grupo», de esta manera ya tendrás el mismo orden y NAs para el grupo «a».
        Luego si solo quieres esa columna la aislas en una nueva tabla y listo

        Espero haberte ayudado

        Isabel

        Reply
        • Borja

          Hola Isabel!

          Mil gracias! Estos días ando un poco ocupado, pero en cuanto pueda lo probaré y te diré si me sirvió.

          Un saludo y gracias! 🙂

          Reply
  17. Vero

    Hola a todos. Muy bueno el blog, bien explicado todo. Si alguien me puede ayudar con una consulta por favor.

    Tengo un dataframe x con las columnas A B C D E. Otro dataframe y con las columas A F G H I. Todas las variables son numéricas. La única columna en común es la A. Un ejemplo de datos sería:

    Dataframe x:
    A B C D E
    1 4 8 0 0
    1 8 9 3 5
    1 3 4 4 9
    2 4 6 3 0
    2 6 8 0 3
    3 8 9 3 5

    Dataframe y:
    A F G H I
    1 2 9 4 6
    1 6 2 7 2
    2 7 4 5 3
    3 2 9 5 3
    3 6 4 0 2

    Debo crear un nuevo dataframe con las columnas A B C E F H que cumpla la siguiente condición:

    (x$A == y$A) & (x$B = y$F)

    Es decir, que A sea el mismo y que el valor F se encuentre entre B y C. El resultado debería ser:

    A B C E F H
    1 4 8 0 6 7
    2 6 8 3 7 5

    No se si está claro el ejemplo. Lo más cercano que encontré es inner_join() pero no me permite escribir la condición de comparación con =. Alguna idea por favor? Gracias!

    Reply
    • Diego Pedro

      Buen dia! Muy bueno el blog y su contenido. Esta bien explicado.
      Vero, fijate que tenes forma de darle la condición al join. Si no lo especificas en en el argumento ‘by’, hace un natural join con las columnas que son comunes en ambos dataset.
      Te dejo el link al manual: busca join y lo vas a encontrar.
      https://cran.r-project.org/web/packages/dplyr/dplyr.pdf

      Reply
  18. Carolina

    Hola,

    En mi caso, yo debo buscar dentro de la columna ID todos elementos que contengan el patrón FR (que va seguido de números, pero no me interesan) y generar una lista con dichos valores. Cómo debo hacerlo?

    Reply
  19. suriel flores

    Buen día, estoy leyendo tu tutorial ya que tengo un data.frame con 162 variables (categóricas y numéricas) y me gustaría obtener otro data frame proveniente del mismo pero unicamente con las variables numéricas. Lo he intentado con subset, con !is.numeric(base), pero no me funciona, ¿se puede realizar desde dplyr?

    Reply
    • Mauricio

      Hola Suriel. Sí, con un poco de ayuda de la biblioteca tidyr. Te dejo un ejemplo:


      > library(dplyr)
      > library(tidyr)

      > mtcars$ejemplo_no_numerico_1 <- 'HOLA'
      > mtcars$ejemplo_no_numerico_2 <- 'MUNDO'

      > var_names <- mtcars %>% summarise_all(typeof) %>% gather() %>% filter(value=='double') %>% select(key)
      > var_names <- var_names$key
      > mtcars %>% select(var_names)

      Reply
  20. Augusto Mendoza

    Hola en tu matriz (mtcars), tu columna cero tiene los nombres de los modelos de coches. Y en la segunda (iris) es vez de nombres tienes numeros.
    Yo tengo una matriz de paises y quiero pasar sus nombres de la columna 1, a la columna cero como en tu primera matriz pero no se como hacerlo, he buscado en internet pero no encuentro solucion. Soy usuario principiante en R, me vendría bien tu ayuda de ser posible.

    Reply
    • Mauricio

      Hola Augusto. En este caso, estos dos conjuntos de datos son dataframes, no matrices. Entonces hay dos posibilidades.
      Una es utilizar el atributo rownames para setearle los valores que desees. Algo así me imagino: rownames(df) <- df$paises.
      El segundo caso es que quieras mover la columna de países a la primera columna del dataframe. Para hacer eso me imagino algo así:
      col_idx <- grep("g", names(df))
      df <- df[, c(col_idx, (1:ncol(df))[-col_idx])]

      Pruebalo y si tienes problemas me dices.

      Reply
  21. Itzel

    Hola, tengo un problema
    Tengo una data frame con varias columnas (por ejemplo el Nombre, Dirección, Telefono), identifique por columna los valores únicos con la función unique(), pero al darme el resultado solo me da los datos únicos de solo esa columna, me interesa saber de esos datos únicos por ejemplo en celular cual es el nombre y dirección correspondiente
    Tengo algo más o menos así, pero me marca error:

    UnicosCel <- select(Registros, unique(Registros$Cel))
    Al igual intente con un subset

    Espero me puedan ayudar!!!

    Reply
  22. Roberto

    Hola,
    Estimado una consulta, al aplicar mutate sobre un dataframe , es posible aplicar select para exportar solo las variables creadas?

    Reply
    • Mauricio

      Hola, tendrías que hacerlo manualmente encadenando el mutate con un select al cual indiques las nuevas columnas.

      Reply
      • Roberto

        Estimado,

        Gracias por la respuesta, lo realice como mencionabas.

        Saludos

        Reply
  23. Gilberto González

    hola, me sirvió mucho. Una consulta, ¿cómo podría modificar ubicar y modificar un sólo dato en una base, utilizando ésta librería, esto es, que ubique, tanto la fila y la columna en la base y remplazar el valor existente por otro?
    Gracias de antemano

    Reply
  24. Roger

    hola a todos, quisiera ayuda de su parte, tengo mi en un data frame 4 columnas la primera es con nombre id, de la segunda a la cuarta tienen los nombres de la inclinación (plana,inclinada,ondulada), la quinta me identifica numericamente el valor máximo de inclinación. Me interesa poner una sexta columna que me indique de el nombre de que columna selecciono ese valor maximo.
    gracias por leer y mas gracias si desean apoyarme.
    saludos……

    Reply
    • Mauricio

      Hola Roger! Bueno, en este momento no recuerdo ninguna función para obtener el valor que quieres. Lo que sí podrías hacer es, dado que son pocas columnas, utilizar varios ifelse para las distintas condiciones.
      Por ejemplo, considerando el dataframe «mtcars», si quieres obtener para cada fila el máximo entre las columnas gear (Number of forward gears) y carb (Number of carburetors), y luego el nombre de la columna en que se da el máximo:


      # DATASET
      mtcars

      # CREO UNA COLUMNA CON EL VALOR MAXION ENTRE gear Y carb
      mtcars$max <- apply(mtcars[c('gear', 'carb')], 1, max) # OBTENGO EL NOMBRE DE LA VARIABLE DE LA CUAL OBTUVE EL VALOR MAXIMO

      ifelse(mtcars$max==mtcars$gear & mtcars$max!=mtcars$carb, 'gear', ifelse(mtcars$max!=mtcars$gear & mtcars$max==mtcars$carb, 'carb', ''))

      Luego me cuentas si esto te sirve, y sino seguimos pensando. Saludos!!

      Reply
      • roger

        funciono hasta cierto punto, el pequño problema es que no asigna el nombre de la columna proveniente cuando el valor maximo es igual para las variables gear y carb. alguna idea para que asigne el nombre de la columan de forma aleatoria en caso de mismos valores max??

        muchas gracias.

        Reply
        • Mauricio

          bueno, lo que sucede es que en el caso de que ambas variables sean iguales lo he dejado vacío intencionalmente. De todos modos podrías poner el nombre la de variable que prefieras, o uno aleatorio, por ejemplo:

          ifelse(mtcars$max==mtcars$gear & mtcars$max!=mtcars$carb, ‘gear’, ifelse(mtcars$max!=mtcars$gear & mtcars$max==mtcars$carb, ‘carb’, sample(c(‘gear’, ‘carb’), 1)))

          Particularmente, me resulta más elegante ponerlo a mano y no aleatorio.

          Reply
          • Roger

            te doy toda la razon, muchas gracias…
            la suscripción que aparece en este link son validas o no es parte de tu pagina???

            saludos. hasta pronto

          • Mauricio

            no problem.
            Sobre la subscripción que me preguntas, no me queda claro a que te refieres. Si es la que aparece en la barra de la derecha, es para agregar a quieres quieran en la lista de correos del sitio, a la cual envió mails cuando salen nuevos post.
            Saludos!!

  25. pedro

    Tengo una consulta quiero aplicar un filtro pero al momento de validar los datos este, no esta filtrando complemtamente, utilizo la funcion subset y filtre y aun así no me es posible (el filtro es para una variable donde selecciono varias opciones)

    Reply
    • Mauricio

      Hola Pedro, con la función filter no deberías tener problemas. Para poder ayudarte necesitaría más detalles del problema que tienes. ¿para seleccionar las categorías utilizas %in%? ¿la columna de categorias es de tipo «character» o «factor»?

      Reply
  26. Valeria López

    Súper bien explicado.
    Me surge una duda, aplicando un filter a una dataset, puedo asignar un valor a una tercer variable, como resultado del filtrado que se hizo?

    Reply
    • Mauricio

      Hola Valeria, Gracias! Sobre tu consulta, no logro entenderla del todo. Si tienes un dataset y lo pasas por la función filter obtienes un nuevo dataset. ¿a qué te refieres con asignar un valor a una tercer variable?

      Reply
  27. Felipe Masís

    Buenísimo!!!!! Muchísimas gracias por compartirlo!!!!

    Reply
    • Mauricio

      Gracias Felipe! Me alegro que te haya resultado de utilidad.

      Reply

Submit a Comment

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *

This site uses Akismet to reduce spam. Learn how your comment data is processed.