Operadores de subconjuntos
En muchas ocasiones, cuando se trabaja con grandes conjuntos de información, solo se está interesado en una pequeña parte de éste conjunto del análisis. Y es por ello que los operadores de subconjuntos permiten acceder, seleccionar o excluir datos que se encuentren dentro de estructuras de datos especificas.
El empleo de subconjuntos puede ser algo difícil de aprender, debido a que para poder dominar tal aspecto, es necesario tener en cuenta otro conjunto de conceptos interrelacionados:
- El lenguaje de programación que se emplea, debido a que cada lenguaje puede tener características diferentes para el manejo de subconjuntos.
- Las diferentes operaciones para seleccionar subconjuntos que pueden haber.
- Los diferentes tipos de subconjuntos.
- El uso de subconjuntos en conjunción con la asignación.
Para dominar los operadores de subconjuntos en R, el objetivo
inicialmente es aprender a dominar el operador más simple para la
selección de subconjuntos en vectores atómicos, el cual se logra
mediante el empleo de los corchetes []
. Posteriormente se buscará
generalizar dichos resultados a dimensiones más altas, tales como
matrices, marcos de datos, arreglos y listas, mediante el empleo de
operadores tales como [[]]
, $
o la combinación de estos.
Vectores atómicos
Tal como se señaló, para la manipular información dentro de vectores,
pueden emplearse el operador de subconjuntos dado por []
, los cuales
sirven para seleccionar, ordenar, filtrar, eliminar información dentro
de un vector.
- Seleccionar: Al emplear enteros positivos dentro de
[]
, lo que se hace es seleccionar valores a los objetos que se encuentren en la posición del entero seleccionado.
Selección en vectores
Supongamos un vector \(x\) dado por los números \(3.1, 7.8, 8.9, 10.5, 2.7, 5.7\), entonces si se desea seleccionar los valores \(8.9\) y \(2.7\) del vector, notamos que estos números se encuentran en la posición \(3\) y \(5\), respectivamente, y por tanto, podemos emplear la notación \[\begin{align*} x[c(3,5)] \end{align*}\] tal que
# Creamos vector numérico
x <- c(3.1, 7.8, 8.9, 10.5, 2.7, 5.7)
# Empleamos operador de subconjuntos para seleccionar los valores 8.9 y 2.7
# los cuales se encuentran en la posición 3 y 5
x[c(3, 5)]
[1] 8.9 2.7
- Duplicar: Al emplear repetidas veces los mismos enteros
positivos dentro de
[]
, lo que se hace es duplicar valores a los objetos que se encuentren en la posición del entero seleccionado.
Duplicar en vectores
También es posible seleccionar dos veces un mismo valor con el fin de duplicarlo, por ejemplo, deseamos seleccionar el valor \(3.1\) y duplicar el valor \(10.5\), entonces como el valor \(3.1\) está en la posición \(1\) y el valor \(10.5\) está en la posición \(4\), podemos emplear la notación \[\begin{align*} x[c(1, 4, 4)] \end{align*}\] en donde se nota que escribimos dos veces el valor \(4\), tal que
# Empleamos operador de subconjuntos para seleccionar los valores 3.1 y
# duplicar el valor 10.5, los cuales se encuentran en la posición 1 y 4
x[c(1, 4, 4)]
[1] 3.1 10.5 10.5
- Reemplazar: Al emplear enteros positivos dentro de
[]
, y aplicar posteriormente el operador de asignación<-
, lo que se hace es que se reasigna el valores de interés, por un nuevo.
Reemplazar en vectores
Para reasignar valores, podemos llamar la posición de interés, y usar el
operador de asignación, para reemplazar dicha posición por el valor de
interés. Suponga que del vector \(x\) queremos reemplazar el valor
\(5.7\), por un \(1000\), entonces, como el valor \(5.7\) se encuentra
en la sexta posición, podemos llamar dicha posición mediante el operador
de subconjuntos y el operador de asignación, mediante la notación
\[\begin{align*}
x[c(6)] <- 1000
\end{align*}\] tal que
# Empleamos operador de subconjuntos para seleccionar el valor 5.7 que se
# encuentra en la posición 6, y asignarle a esta posición el valor 1000
x[c(6)] <- 1000
x
[1] 3.1 7.8 8.9 10.5 2.7 1000.0
- Eliminar: Al emplear enteros negativos dentro de
[]
, lo que se hace es eliminar los objetos que se encuentren en la posición del entero seleccionado.
Eliminar
Supongamos un vector \(y\) dado por los números \(3.1, NA, 8.9, 10.5, 2.7, 5.7\), entonces si se desea eliminar el valor NA del vector, notamos que este valor se encuentran en la posición \(2\), y por tanto, podemos emplear la notación \[\begin{align*} y[-c(2)] \end{align*}\] dentro del operador de subconjuntos para eliminar dicho valor, tal que
# Creamos vector numérico
y <- c(3.1, NA, 8.9, 10.5, 2.7, 5.7)
# Empleamos operador de subconjuntos para eliminar el valor NA el cual se
# encuentran en la posición 2
y[-c(2)]
[1] 3.1 8.9 10.5 2.7 5.7
- Vectores lógicos o condicionales: También podemos emplear
vectores lógicos o condicionales dentro del operador de subconjuntos
[]
, para seleccionar o filtrar aquellos valores de interés.
Seleccionar con vectores lógicos
Supongamos nuevamente el vector \(x\) dado por los números \(3.1, 7.8, 8.9, 10.5, 2.7, 5.7\), entonces podemos usar un vector de TRUE o FALSE para seleccionar los valores de interés. Supongamos que deseamos seleccionar solo los dos primeros valores del vector \(x\), entonces podemos emplear un vector de la forma \[\begin{align*} x[c(T,T,F,F,F,F)] \end{align*}\] tal que
# Empleamos operador de subconjuntos con un vector lógico para seleccionar
# los dos primeros valores del vector
x[c(T, T, F, F, F, F)]
[1] 3.1 7.8
Filtrar con un condicional
También podemos emplear condicionales para filtrar valores, suponga que se quiere filtrar aquellos valores que sean menores a \(4\) del vector \(x\), entonces podemos usar el condicional \[\begin{align*} x[x < 4] \end{align*}\] tal que
# Empleamos operador de subconjuntos con un condicional para filtrar
# aquellos valores que cumplen la condición de ser menor a 4
x[x < 4]
[1] 3.1 2.7
Filtrar con varios condicionales
Adicionalmente, podemos emplear más de un condicional a la vez, en donde
podemos emplear el operador de conjunción |
o disyunción
&
, para agregar varios condicionales. Suponga que queremos
filtrar del vector y, los valores que sean mayores o igual a
5 o sean NA. Para
ello empleamos la notación \[\begin{align*}
y[y >= 5 | is.na(y)]
\end{align*}\] tal que
# Empleamos operador de subconjuntos con condicionales para filtrar aquellos
# valores mayores o iguales a 5 o que sean NA
y[y >= 5 | is.na(y)]
[1] NA 8.9 10.5 5.7
- Vector de caracteres También puede pasar que los vectores de interés, no sean numéricos si no que sean cadenas de caracteres o en su defecto, que sean numéricos y posean cadenas de caracteres asociados. En dicho caso, podemos emplear los operadores de subconjuntos escribiendo entre comillas aquellos caracteres de interés.
Vector de caracteres
Supongamos un vector \(w\) dado por los caracteres “Daniel”, “Carlos”, “Paola”, “Daniel”, “Juan”, “Ana”, entonces si estamos interesados en aquellos valores que contienen la cadena de caracteres “uno”, entonces podemos emplear la notación \[\begin{align*} x[x == “Daniel”] \end{align*}\] para filtrar dichos valores de interés, tal que
# Creamos vector de caracteres
w <- c("Daniel", "Carlos", "Paola", "Daniel", "Juan", "Ana")
# Empleamos operador de subconjuntos, junto con el operador de igualdad para
# filtrar por caracteres
w[w == "Daniel"]
[1] "Daniel" "Daniel"
Vector con nombres
Similarmente, supongamos un vector numérico \(z\), que posee caracteres asociados a los números, tal que “Daniel” = 4, “Carlos” = 8, “Paola” = 12.4, “Ana” = 2.4, “Juan”= 8, “Ana” = 1. Entonces, si queremos filtrar por “Ana” empleando el operador de subconjuntos, podemos emplear la notación \[\begin{align*} z[\text{names}(z) == “Ana”] \end{align*}\] o la notación numérica \[\begin{align*} z[z == 2.4 | z == 1.0] \end{align*}\] tal que
# Creamos vector numérico con caracteres
z <- c(Daniel = 4, Carlos = 8, Paola = 12.4, Ana = 2.4, Juan = 8, Ana = 1)
# Empleamos operador de subconjuntos, junto con la función names() y el
# operador de igualdad, para filtrar por caracteres
z[names(z) == "Ana"]
Ana Ana
2.4 1.0
# Empleamos operador de subconjuntos, junto con el operador de igualdad para
# filtrar por número
z[z == 2.4 | z == 1]
Ana Ana
2.4 1.0
Matrices y arreglos
El caso de las matrices y arreglos, se tiene que la dimensión de los
objetos pueden ser de 2d o más. Por ello podemos emplear el
operador de subconjuntos []
, separando por coma cada dimensión. Por
ejemplo, dado que una matriz es de 2d, entonces podemos emplear
el operador de subconjuntos, separando por una coma, [ , ]
, en donde,
el valor antes de la coma indica lo valores de fila de interés, y los
valores después de la coma indican los valores de columna de interés.
Similarmente, para el caso de los arreglos, el cual puede ser de más de 2d, entonces podemos emplear el operador de subconjuntos, separando por una coma cada dimensión adicional.
Matrices por entrada
Supongamos una matriz M de dimensión \(2\times3\) dada por
\[\begin{align*} M = \begin{bmatrix}6 & 2 & 3 \\12 & 7 & 9 \end{bmatrix}_{2\times3} \end{align*}\]Entonces, si deseamos filtrar el valor \(9\) que se encuentra en la posición \(2,3\) (fila \(2\), columna \(3\)), podemos emplear el operador de subconjuntos con la notación \[\begin{align*} M[2,3] \end{align*}\] tal que
# Creamos la matriz
M <- matrix(c(6, 2, 3, 12, 7, 9), nrow = 2, ncol = 3, byrow = T)
# Empleamos operador de subconjuntos, para seleccionar valor 9 de la matriz
# M
M[2, 3]
[1] 9
Matrices por fila o columna
Ahora, si queremos seleccionar solo una fila o columna, entonces podemos emplear el operador de asignación, dejando vacío el valor antes de la coma, si deseamos filtrar por columna, o dejar vacío el valor después de la coma, si deseamos filtrar por fila. Por ejemplo, si queremos filtrar por la columna \(1\) de la matriz M, empleando la notación \[\begin{align*} M[\;,1] \end{align*}\] en donde se puede notar que no hay ningún valor asignado antes de la coma.
# Empleamos operador de subconjuntos, para seleccionar la columna número 1
# de la matriz M
M[, 1]
[1] 6 12
Arreglo por entrada
Funcionan similar a las matrices, pero con la diferencia de éstos pueden tener dimensiones extra. Por ello, es cuestión de agregar las nuevas dimensiones dentro del operador de subconjuntos, separando cada dimensión mediante comas. Por ejemplo se tiene un arreglo \(2\times2\times3\), formado por las tres matrices \(A_1, A_2, A_3\), \(2\times2\) siguientes \[\begin{align*} A_1 = \begin{bmatrix}6 & 2 \\7 & 9 \end{bmatrix}_{2\times2} \qquad A_2 = \begin{bmatrix}3 & 7 \\12 & 8 \end{bmatrix}_{2\times2} \qquad A_3 = \begin{bmatrix}13 & 2 \\3 & 11 \end{bmatrix}_{2\times2} \end{align*}\] Entonces, si deseamos filtrar el valor \(3\) que se encuentra en la posición \(2,1\) (fila \(2\), columna \(1\)) de la tercera matriz, podemos emplear el operador de subconjuntos con la notación \[\begin{align*} A[2,1,3] \end{align*}\] tal que
# Creamos las tres matrices
A1 <- matrix(c(6, 2, 7, 9), nrow = 2, ncol = 2, byrow = T)
A2 <- matrix(c(3, 7, 12, 8), nrow = 2, ncol = 2, byrow = T)
A3 <- matrix(c(13, 2, 3, 11), nrow = 2, ncol = 2, byrow = T)
# Creamos arreglo
A <- array(c(A1, A2, A3), dim = c(2, 2, 3))
# Empleamos operador de subconjuntos, para seleccionar valor 3 de la tercera
# matriz del arreglo A, que se encuentra en la posición 2,1.
A[2, 1, 3]
[1] 3
Arreglo por fila o columna
Ahora, si queremos seleccionar solo una fila o columna, entonces podemos emplear el operador de asignación, dejando vacíos los valores antes de la primera coma y después de la segunda, tercera…. coma (dependiendo de la dimensión del arreglo), si deseamos filtrar por columna, o dejar vacío los valores después la primera, segunda, tercera…. coma (dependiendo de la dimensión del arreglo), si deseamos filtrar por fila. Por ejemplo, si queremos filtrar por la fila \(2\) del arreglo A, podemos emplear la notación \[\begin{align*} A[2,\; ,\; ] \end{align*}\] en donde, solo se usan dos comas debido a que la dimensión del arreglo es de \(3d\).
# Empleamos operador de subconjuntos, para seleccionar la segunda fila de
# cada matriz dentro del arreglo A.
A[2, , ]
[,1] [,2] [,3]
[1,] 7 12 3
[2,] 9 8 11
Arreglo por dimensiones superiores
Para filtrar por un dimensión superior a \(2d\), es necesario identificar el orden de interés del arreglo, y escribir el valor para la dimensión luego de la coma, asociada a la dimensión en la que se está interesado. Por ejemplo, \(A\) es un arreglo de \(2\times2\times3\), así que si estoy interesado solo en la segunda matriz, entonces puedo escribir un \(2\) luego de la segunda coma, ya que estoy interesado en la tercera dimensión del arreglo. Dicha notación sería \[\begin{align*} A[\;, \; ,2] \end{align*}\] en donde, se observa, que los valores asociados a las filas y las columnas se encuentra vacíos.
# Empleamos operador de subconjuntos, para seleccionar la segunda matriz
# dentro del arreglo A.
A[, , 2]
[,1] [,2]
[1,] 3 7
[2,] 12 8
Marco de datos
Los marcos de datos poseen un comportamiento similar a los vectores con
nombres o matrices, debido a que éstas pueden encontrarse en un conjunto
de 1d (cuando posee un solo vector) o 2d (cuando hay
dos o más vectores). Por tanto, para manipular los marcos de datos,
podemos emplear el operador de subconjuntos []
, separando por coma la
las filas de las columnas.
Adicionalmente, los marcos de datos, poseen un operador de subconjuntos
adicionales, el cual posee el símbolo $
, el cual se emplea luego del
nombre del dataframe y permite filtrar por el nombre de las columnas del
marco de datos.
Marco de datos
Para ilustrar el modo de trabajar un marco de datos como un vector con nombres, supongamos la siguiente base de datos.
DatF <- data.frame(Num = 1:10, Car = letters[1:10], Log = c(rep(T, 3), rep(F,
3), rep(T, 4)))
DatF
Num Car Log
1 1 a TRUE
2 2 b TRUE
3 3 c TRUE
4 4 d FALSE
5 5 e FALSE
6 6 f FALSE
7 7 g TRUE
8 8 h TRUE
9 9 i TRUE
10 10 j TRUE
Marco de datos como vectores con nombres
Entonces, suponga que deseamos filtrar columna “Car”, empleando la forma usada en vectores con nombres, podemos usar el operador de subconjuntos, para localizar la columna de interés, mediante la notación
\[\begin{align*} DatF[``Car"] \end{align*}\]tal que
# Empleamos operador de subconjuntos [], como en el caso de vectores con
# nombres para seleccionar la columna con nombre 'Car'
DatF["Car"]
Car
1 a
2 b
3 c
4 d
5 e
6 f
7 g
8 h
9 i
10 j
Alternativamente, podemos usar el operador de asignación $
luego del nombre del marco de datos, seguido del nombre de la variable
de interés, en donde la notación usada sería de la forma
# Empleamos operador de subconjuntos $, para seleccionar la columna con
# nombre 'Car'
DatF$Car
[1] a b c d e f g h i j
Levels: a b c d e f g h i j
Puede apreciarse que el empleo de un método u el otro ofrece resultados diferentes, en donde al usar el primer método se conserva la clase “data.frame”, mientras que, con el segundo método se maneja la clase interna de la columna, que en este caso es tipo factor.
# Observamos la clase del os objetos
class(DatF["Car"])
[1] "data.frame"
class(DatF$Car)
[1] "factor"
Marco de datos como matriz
Si queremos mediante el operador de asignación empleado para matrices,
\[ , \]
, entonces para filtrar por la columna
“Car”, podemos emplear la siguiente notación
en donde, se emplea la segunda columna, ya que la variable “Car”, es la segunda columna del marco de datos.
# Empleamos operador de subconjuntos [], como en el caso de matrices para
# seleccionar la segunda columna 2
DatF[, 2]
[1] a b c d e f g h i j
Levels: a b c d e f g h i j
De lo anterior, vemos que la salida obtenida, es similar a la obtenida
cuando filtramos la columna mediante el operador de asignación
$
# Observamos la clase del objeto
class(DatF[, 2])
[1] "factor"
Listas
Para el manejo de listas, es necesario manipular los operadores de
asignación anteriormente presentados, debido a que en las listas es
posible incluir cualquier tipo de objeto, y adicionalmente, hay que
aprender a manipular el operador de subconjuntos [[]]
, el cual es
parecido al operador []
, pero con la diferencia de que [[]]
extrae
el objetos de las listas. Resultado similar puede ser obtenido con el
operador de subconjuntos $
Listas
Supongamos que poseemos una lista, la cual contiene un vector con nombres, una matriz, un arreglo, un marco de datos y una función.
# Creamos un marco de datos con objetos creados previamente
Lista <- list(VC = z, MT = M, AR = A, DF = DatF, FU = function(x) class(x))
Lista
$VC
Daniel Carlos Paola Ana Juan Ana
4.0 8.0 12.4 2.4 8.0 1.0
$MT
[,1] [,2] [,3]
[1,] 6 2 3
[2,] 12 7 9
$AR
, , 1
[,1] [,2]
[1,] 6 2
[2,] 7 9
, , 2
[,1] [,2]
[1,] 3 7
[2,] 12 8
, , 3
[,1] [,2]
[1,] 13 2
[2,] 3 11
$DF
Num Car Log
1 1 a TRUE
2 2 b TRUE
3 3 c TRUE
4 4 d FALSE
5 5 e FALSE
6 6 f FALSE
7 7 g TRUE
8 8 h TRUE
9 9 i TRUE
10 10 j TRUE
$FU
function(x) class(x)
<environment: 0x000000001d9d5fb0>
Adicionalmente, supongamos que deseamos extraer la matriz que se
encuentra dentro de lista. Dado que la matriz es el segundo objeto de la
lista, podemos emplear tres alternativas. Usar la posición \(2\) debido
a que es el segundo objeto de la lista, usar el nombre que posee dentro
de la lista, o usar el operador $
seguido del nombre dentro
de la lista
\[\begin{align*}
Lista[[2]] \quad \text{ ó } \quad Lista[[``MT"]] \quad \text{ ó } \quad Lista\$MT
\end{align*}\]
Estas tres formas funcionan exactamente igual, puesto que permiten
extraen totalmente de la lista, el objeto de interés.
# Empleamos operador de subconjuntos [[]], para extraer el segundo objeto
# guardado en la lista
Lista[[2]]
[,1] [,2] [,3]
[1,] 6 2 3
[2,] 12 7 9
# Observamos la clase del objeto resultante
class(Lista[[2]])
[1] "matrix"
Caso contrario ocurre cuando realizamos la extracción mediante el otro operador de subconjuntos, en donde se aprecia que el objeto sigue tendiendo la característica de lista.
# Empleamos operador de subconjuntos [], para extraer el segundo objeto
# guardado en la lista
Lista[2]
$MT
[,1] [,2] [,3]
[1,] 6 2 3
[2,] 12 7 9
# Observamos la clase del objeto resultante
class(Lista[2])
[1] "list"
Una vez extraído el objeto de interés dentro de la lista, pueden emplearse las operaciones descritas previamente para vectores, matrices, etc, etc. Por ejemplo, tenemos la lista, deseamos extraer la segunda matriz del objeto AR, entonces podemos emplear la notación \[\begin{align*} Lista$AR[\;, \;, 2] \end{align*}\] tal que
# Empleamos operador de subconjuntos $, para extraer el arreglo AR guardado
# en la lista, y simultáneamente se extrae la segunda matriz del arreglo
Lista$AR[ , , 2]
[,1] [,2]
[1,] 3 7
[2,] 12 8
En donde se aprecia, que el objeto AR es un arreglo, y en consecuencia, para extraer la segunda matriz, debe usarse el operador de asignación, con un \(2\) luego de la segunda coma, debido a que estamos interesados en la segunda matriz