Una de las grandes fortalezas de R es su capacidad para evaluar funciones sobre vectores completos, evitando así la necesidad de bucles y subíndices. Las funciones vectoriales más importantes se enumeran en la Tabla 2.4.
Tabla 2.4. Funciones vectoriales utilizadas en R
| Operación | Sentido |
|---|---|
| max(x) | valor máximo en x |
| min(x) | valor mínimo en x |
| sum(x) | total de todos los valores en x |
| mean(x) | media aritmética de los valores en x |
| median(x) | valor de la mediana en x |
| range(x) | vector de min(x) y max(x) |
| var(x) | varianza muestral de x |
| cor(x,y) | correlación entre vectores x e y |
| sort(x) | una versión ordenada de x |
| rank(x) | vector de los rangos de los valores en x |
| order(x) | un vector entero que contiene la permutación para clasificar x en orden ascendente |
| quantile(x) | vector que contiene el mínimo, el cuartil inferior, la mediana, el cuartil superior y el máximo de x |
| cumsum(x) | vector que contiene la suma de todos los elementos hasta ese punto |
| cumprod(x) | vector que contiene el producto de todos los elementos hasta ese punto |
| cummax(x) | vector de números no decrecientes que son los máximos acumulativos de los valores en x hasta ese punto |
| cummin(x) | vector de números no crecientes que son los mínimos acumulativos de los valores en x hasta ese punto |
| pmax(x,y,z) | vector, de longitud igual al mayor de x, y o z, que contiene el máximo de x, y o z para el enésima posición en cada |
| pmin(x,y,z) | vector, de longitud igual al mayor de x, y o z, que contiene el mínimo de x, y o z para el enésima posición en cada |
| colMeans(x) | columna media del marco de datos o matriz x |
| colSums(x) | totales de columna del marco de datos o matriz x |
| rowMeans(x) | fila media del marco de datos o matriz x |
| rowSums(x) | totales de fila del marco de datos o matriz x |
y <- c(8,3,5,7,6,6,8,9,2,3,9,4,10,4,11)
Algunas funciones vectoriales producen un solo número:
mean(y <- c(8,3,5,7,6,6,8,9,2,3,9,4,10,4,11))## [1] 6.333333
range(y <- c(8,3,5,7,6,6,8,9,2,3,9,4,10,4,11))## [1] 2 11
Aqui se muestra que el minimo sue 2 y el maxion fue 11.
fivenum(y <- c(8,3,5,7,6,6,8,9,2,3,9,4,10,4,11))## [1] 2.0 4.0 6.0 8.5 11.0
Este es el famoso resumen de cinco números de Tukey´s: el mínimo, la bisagra inferior, la mediana, la bisagra superior y el máximo; Quizás la función vectorial más útil en R es la table. Necesitas verlo en acción para apreciar lo bueno que es.
counts <- rnbinom(10000,mu=0.92,size=1.1)Aquí hay un vistazo a los primeros 30 valores en counts:
counts[1:30]## [1] 0 0 3 0 3 0 1 1 2 1 0 1 2 0 2 2 0 1 0 0 2 0 0 0 1 3 0 0 1 1
La pregunta es esta: ¿cuántos ceros hay en el vector completo de 10 000 números, cuántos 1, y así sucesivamente hasta el valor más grande dentro de las cuentas?
Una tarea formidable para ti o para mí, pero para R es solo:
table(counts <- rnbinom(10000,mu=0.92,size=1.1))##
## 0 1 2 3 4 5 6 7 8 9 10 12
## 5101 2620 1204 591 274 119 51 25 11 2 1 1
Había 5167 ceros, 2535 unos, 1229 dos, 563 tres, 277 cuatro, 130 cinco, 55 seis y así sucesivamente hasta las cuentas más grandes.
Una de las funciones más importantes en todo R es tapply. . No parece mucho por el nombre, pero lo usará una y otra vez para calcular medias, varianzas, tamaños de muestra, mínimos y máximos. Con datos meteorológicos, por ejemplo, podríamos querer las temperaturas medias de 12 meses en lugar del promedio de todo el año. Tenemos una variable de respuesta, temperature, y una variable explicativa categórica, month:
data<-read.table("/cloud/project/temperatures.txt",header = T)
attach(data)
names(data)## [1] "temperature" "lower" "rain" "month" "yr"
La función que queremos aplicar es mean. Todo lo que hacemos es invocar el tapply función con tres argumentos: la variable de respuesta, la variable explicativa categórica y el nombre de la función que queremos aplicar:
tapply(temperature,month,mean)## 1 2 3 4 5 6 7 8
## 7.930051 8.671136 11.200508 13.813708 17.880847 20.306151 22.673854 23.104924
## 9 10 11 12
## 19.344211 15.125976 10.720702 8.299830
Es fácil aplicar otras funciones de la misma manera: aquí están las variaciones mensuales
tapply(temperature,month,var)## 1 2 3 4 5 6 7 8
## 11.568976 10.743512 10.895535 12.400164 16.517578 14.501635 13.962581 13.538360
## 9 10 11 12
## 9.771223 7.865736 9.510432 11.518656
y el mínimo mensual
tapply(temperature,month,min)## 1 2 3 4 5 6 7 8 9 10 11 12
## -6.8 -3.5 1.5 2.8 8.8 11.5 14.3 15.0 7.5 8.3 0.5 -1.8
Si R no tiene una función incorporada para hacer lo que desea (Tabla 2.4), entonces puede escribir fácilmente la suya propia. Aquí, por ejemplo, hay una función para calcular el error estándar de cada media (estas se llaman funciones anónimas en R, porque no tienen nombre):
tapply(temperature,month,function(x) sqrt(var(x)/length(x)))## 1 2 3 4 5 6 7 8
## 0.1401489 0.1414445 0.1358934 0.1476242 0.1673197 0.1596439 0.1539661 0.1516091
## 9 10 11 12
## 0.1309294 0.1155612 0.1291703 0.1398438
El tapply es una función muy flexible. Puede producir tablas multidimensionales simplemente reemplazando la variable month por un list de variables categóricas. Aquí están los medios mensuales calculados por separado para cada año, según lo especificado por list(yr,month). La variable que nombre primero en la lista (año) aparecerá como la fila de la tabla de resultados y la segunda aparecerá como las columnas (month):
tapply(temperature,list(yr,month),mean)[,1:6]## 1 2 3 4 5 6
## 1987 3.170968 6.871429 8.132258 14.92667 15.60645 17.73667
## 1988 8.048387 8.248276 9.959375 12.74483 17.31935 18.71667
## 1989 8.841935 9.482143 11.919355 11.09333 20.40323 21.23667
## 1990 9.445161 11.028571 12.487097 13.80000 20.16129 18.51667
## 1991 6.980645 4.817857 12.022581 13.14333 15.58065 16.88000
## 1992 6.964516 8.686207 11.477419 13.35000 20.45806 22.21667
## 1993 10.119355 6.985714 11.209677 14.17000 17.79355 21.10000
## 1994 8.825806 7.217857 11.806452 12.61667 16.23226 20.86000
## 1995 8.309677 10.439286 10.667742 14.79667 18.74063 19.94483
## 1996 7.019355 6.065517 8.487097 13.99667 14.38710 21.93667
## 1997 4.932258 10.178571 13.370968 15.00667 18.17419 19.93000
## 1998 8.759375 11.242857 11.719355 12.55333 19.43226 19.35000
## 1999 9.523333 8.485714 11.790323 14.65000 18.94839 20.00667
## 2000 8.229032 10.324138 11.900000 12.59000 18.22581 20.63333
## 2001 7.067742 9.121429 9.012903 12.65667 18.96452 20.52667
## 2002 9.067742 11.396429 12.319355 15.68667 16.81290 19.67667
## 2003 8.012903 8.171429 13.425806 15.69000 17.36452 22.80000
## 2004 8.261290 8.993103 10.354839 15.17000 17.98065 21.73667
## 2005 9.116129 7.032143 10.787097 13.78333 17.12258 22.00000
Los subíndices [,1:6] simplemente restrinje la producción a los primeros seis meses. Puede ver de inmediato que enero (mes 1) de 1993 fue excepcionalmente cálido y enero de 1987 excepcionalmente frío. Solo hay una cosa sobre tapply eso podría confundirte. Si intenta aplicar una función que tiene protección incorporada contra valores faltantes, entonces tapply no puede hacer lo que quiere, produciendo NA en lugar de la respuesta numérica. Esto es más probable que suceda con la función de media porque su valor predeterminado es producir NA cuando faltan uno o más valores. El remedio es proporcionar un argumento extra para tapply, especificando que desea ver el promedio de los valores que no faltan. Usar na.rm=TRUE to remove the missing values like this:
tapply(temperature,yr,mean,na.rm=TRUE)## 1987 1988 1989 1990 1991 1992 1993 1994
## 13.27014 13.79126 15.54986 15.62986 14.11945 14.61612 14.30984 15.12877
## 1995 1996 1997 1998 1999 2000 2001 2002
## 15.81260 13.98082 15.63918 15.02568 15.63736 14.94071 14.90849 15.47589
## 2003 2004 2005
## 16.03260 15.25109 15.06000
Es posible que desee recortar algunos de los valores extremos antes de calcular la media (la media aritmética es muy sensible a los valores atípicos). los trim opción le permite especificar la fracción de los datos (entre 0 y 0.5) que desea omitir de las colas izquierda y derecha del vector ordenado de valores antes de calcular la media de los valores centrales:
tapply(temperature,yr,mean,trim=0.2)## 1987 1988 1989 1990 1991 1992 1993 1994
## 13.45068 13.74500 14.99726 15.16301 13.92237 14.32091 14.28000 14.64658
## 1995 1996 1997 1998 1999 2000 2001 2002
## 15.25571 13.75845 15.54064 14.91500 15.44364 14.59318 14.63333 15.33927
## 2003 2004 2005
## 15.70959 15.04136 15.02009
Supongamos que tenemos dos variables de respuesta (y, z) y dos variables explicativas (x, w) que podríamos querer usar para resumir funciones como la media o la varianza de y / z. los aggregate función tiene un método de fórmula que permite resúmenes elegantes de cuatro tipos:
Esto es muy útil para eliminar la pseudoreplicación de los marcos de datos. Aquí hay un ejemplo usando un marco de datos con dos variables continuas (Growth.rate and pH) y tres variables explicativas categóricas (Water, Detergent y Daphnia):
data<-read.table("/cloud/project/phDaphnia.txt",header=T)
names(data)## [1] "Growth.rate" "Water" "Detergent" "Daphnia" "pH"
Aquí hay un uso uno a uno del agregado para encontrar la tasa de crecimiento promedio en las dos muestras de water:
aggregate(Growth.rate~Water,data,mean)Aquí hay un uso de uno a muchos para observar la interacción entre el water y el detergent:
aggregate(Growth.rate~Water+Detergent,data,mean)Finalmente, aquí hay un uso de “muchos a muchos” para encontrar el pH medio y la growth.rate media para la interacción entre water y detergent:
aggregate(cbind(pH,Growth.rate)~Water+Detergent,data,mean)Aquí hay tres vectores de la misma longitud, x, y y z. La función mínima paralela, pmin, encuentra el mínimo de cualquiera de las tres variables para cada subíndice, y produce un vector como resultado (de longitud igual al mayor de x, y, o z)
x <- c( 0.99822644, 0.98204599, 0.20206455, 0.65995552, 0.93456667, 0.18836278)Y <- c(0.51827913, 0.30125005, 0.41676059, 0.53641449, 0.07878714, 0.49959328)z <- c( 0.26591817, 0.13271847, 0.44062782, 0.65120395, 0.03183403, 0.36938092)pmin(x,Y,z)## [1] 0.26591817 0.13271847 0.20206455 0.53641449 0.03183403 0.18836278
Así, el primer y segundo mínimos provinieron de z, el tercero de x, el cuarto de y, el quinto de z, y el sexto de x. Las funciones min y max producen resultados escalares, no vectores.
La función vectorial tapply es una de las funciones vectoriales más importantes y útiles para dominar. La ‘t’ significa ‘tabla’ y la idea es aplicar una función para producir una tabla a partir de los valores en el vector, basada en una o más variables de agrupación (a menudo la agrupación es por niveles de factor). Esto suena mucho más complicado. de lo que realmente es:
data <- read.table("/cloud/project/daphnia.txt",header=T)
attach(data)
names(data)## [1] "Growth.rate" "Water" "Detergent" "Daphnia"
La variable de respuesta es Growth.rate y las otras tres variables son factores. Supongamos que queremos la tasa de crecimiento media para cada detergente
tapply(Growth.rate,Detergent,mean)## BrandA BrandB BrandC BrandD
## 3.884832 4.010044 3.954512 3.558231
Esto produce una tabla con cuatro entradas, una para cada nivel del factor denominado Detergent. para producir un tabla bidimensional ponemos las dos variables de agrupación en una lista. Aquí calculamos la tasa de crecimiento mediana para tipo water y clon de dafnia:
tapply(Growth.rate,list(Water,Daphnia),median)## Clone1 Clone2 Clone3
## Tyne 2.874053 3.908644 4.618288
## Wear 2.590373 5.532726 4.302642
La primera variable de la lista crea las filas de la tabla y la segunda las columnas.
Hay una función importante llamada which para encontrar direcciones dentro de vectores. El vector y parece este:
y <- c(8,3,5,7,6,6,8,9,2,3,9,4,10,4,11)Supongamos que queremos saber qué elementos de y contienen valores mayores que 5. Escribimos:
which(y>5)## [1] 1 4 5 6 7 8 11 13 15
Observe que la respuesta a esta pregunta es un conjunto de subíndices. No usamos subíndices dentro del wich en sí. La función se aplica a toda la matriz. Para ver los valores de y que son mayores que 5, Sólo tipo:
y[y>5]## [1] 8 7 6 6 8 9 9 10 11
Tenga en cuenta que este es un vector más corto que el propio y, porque los valores de 5 o menos se han omitido:
length(y)## [1] 15
length(y[y>5])## [1] 9
Encontrar el valor en un vector que está más cerca de un valor específico es sencillo usando which. el vector xv contiene 1000 números aleatorios de una distribución normal con media = 100 y desviación estándar = 10:
xv<- rnorm(1000,100,10)Aquí, queremos encontrar el valor de xv más cercano a 108.0. La lógica es calcular la diferencia entre 108 y cada uno de los 1000 números aleatorios, luego encuentra cuál de estas diferencias es la más pequeña. Esto es lo que el código R se parece a:
which(abs(xv-108)==min(abs(xv-108)))## [1] 462
El valor más cercano a 108.0 está en la ubicación 767 dentro de xv. Pero, ¿qué tan cerca de 108.0 está este valor 767? Nosotros use 767 como subíndice en xv para averiguarlo:
xv[767]## [1] 113.9709
Ahora podemos escribir una función para devolver el valor más cercano a un valor específico (sv) en cualquier vector (xv):
closest <- function(xv,sv){xv[which(abs(xv-sv)==min(abs(xv-sv)))]}y ejecútalo así:
closest(xv,108)## [1] 108.0032
Estos tres conceptos relacionados son importantes, y uno de ellos (orden) es difícil de entender a primera vista. Tomemos un ejemplo simple:
houses<-read.table("/cloud/project/houses.txt",header=T)
attach(houses)
names(houses)## [1] "Location" "Price"
Aplicamos las tres funciones diferentes al vector llamado Precio:
ranks<-rank(Price)sorted<-sort(Price)ordered<-order(Price)Luego hacemos un marco de datos de los cuatro vectores como este:
view<- data.frame(Price, ranks, sorted, ordered)
viewLos precios en sí no están en una secuencia particular. la columna ranks contiene el valor que es el rango del punto de datos en particular (valor de Price), donde 1 se asigna al punto de datos más bajo y length(Price) – aquí 12 – se asigna al punto de datos más alto. Así que el primer elemento, un precio de 325, resulta ser el más alto valor en price. Debe verificar que hay 11 valores menores que 325 en el vector llamado price. Los rangos fraccionarios indican empates. Hay dos 188 en Price y sus rangos son 8 y 9. Debido a que están empatados, cada uno obtiene el promedio de sus dos rangos (8 + 9)/2 = 8.5. El precio más bajo es 95, indicado por un rango de 1.
El vector ordenado es muy sencillo. Contiene los valores de price ordenados en orden ascendente. Si desea clasificar en orden descendente, use la función de orden inverso rev de esta manera:
y <- rev(sort(x))
Tenga en cuenta que sort es potencialmente muy peligroso, porque desacopla valores que podrían necesitar estar en el mismo fila del marco de datos (por ejemplo, porque son las variables explicativas asociadas con un valor particular de la variable de respuesta). Es una mala práctica, por lo tanto, escribir x <- sort(x), sobre todo porque no hay Función ‘desordenar’.
Esta es la más importante de las tres funciones, y mucho más difícil de entender a primera vista. Los números en esta columna son subíndices entre 1 y 12. La función de orden devuelve un vector entero que contiene la permutación que ordenará la entrada en orden ascendente. Tendrás que pensar en esto. El valor más bajo de price es 95. Mire el marco de datos y pregúntese cuál es el subíndice en el vector original llamado price donde ocurrió 95. Escaneando hacia abajo en la columna, lo encuentra en la fila número 9. Este es el primer valor en ordered,ordered[1]. ¿Dónde se encuentra el siguiente valor más pequeño (101) dentro de Price? Está en la posición 6, por lo que está ordered[2]. El tercer valor más pequeño de price (117) está en la posición 10, por lo que se ordered[3*]. y asi sucesivamente.
Esta función es particularmente útil para ordenar marcos de datos, Usar order con subíndices es una opción mucho más segura que usar sort, porque con sort los valores de la variable de respuesta y las variables explicativas podrían desacoplarse con resultados potencialmente desastrosos si esto no se realiza en el momento en que se realizó el modelado. La belleza del order es que podemos usar order(Price) omo subíndice de Location para obtener la lista de ubicaciones ordenadas por precio:
Location[order(Price)]## [1] "Reading" "Staines" "Winkfield" "Newbury" "Bracknell"
## [6] "Camberley" "Bagshot" "Maidenhead" "Warfield" "Sunninghill"
## [11] "Windsor" "Ascot"
Cuando vea que se usa así, podrá ver exactamente por qué la función se llama order. Si quieres invertir el orden, simplemente use la función rev de esta manera:
Location[rev(order(Price))]## [1] "Ascot" "Windsor" "Sunninghill" "Warfield" "Maidenhead"
## [6] "Bagshot" "Camberley" "Bracknell" "Newbury" "Winkfield"
## [11] "Staines" "Reading"
Asegúrese de comprender por qué algunos de los corchetes son redondos y otros cuadrados.
La diferencia se ve mejor con un ejemplo simple. Aquí hay un vector names:
names <- c("Williams","Jones","Smith","Williams","Jones","Williams")Podemos ver cuantas veces aparece cada nombre usando la table:
table(names)## names
## Jones Smith Williams
## 2 1 3
Está claro que el vector contiene solo tres nombres diferentes. La función llamada unique extrae estos tres nombres únicos, creando un vector de longitud 3, sin clasificar, en el orden en que se encuentran los nombres en el vector:
unique(names)## [1] "Williams" "Jones" "Smith"
En cambio, la función llamada duplicated produce un vector, de la misma longitud que el vector de nombres, que contiene los valores lógicos FALSE o TRUE. dependiendo de si ese nombre ya ha aparecido o no (leyendo desde la izquierda). Necesita ver esto en acción para comprender lo que está sucediendo y por qué podría ser útil:
duplicated(names)## [1] FALSE FALSE FALSE TRUE TRUE TRUE
Los primeros tres nombres no están duplicados, (FALSE). pero los tres últimos están todos duplicados (TRUE). Nosotros podemos imitar el unique función mediante el uso de este vector como subíndices como este:
names[!duplicated(names)]## [1] "Williams" "Jones" "Smith"
Nótese el uso del operador NOT (!) delante del duplicated función. Ahí lo tiene: si desea un vector acortado, que contenga solo los valores únicos en los nombres, use unique, pero si desea un vector de la misma longitud que los nombres, use duplicated Puede usar esto para extraer valores de un vector diferente (salarios, por ejemplo) si desea el salario medio, ignorando las repeticiones:
salary<-c(42,42,48,42,42,42)
mean(salary)## [1] 43
salary[!duplicated(names)]## [1] 42 42 48
mean(salary[!duplicated(names)])## [1] 44
Tenga en cuenta que esta no es la misma respuesta que se obtendría al omitir los salarios duplicados, porque dos de las personas (Jones y Williams) tenían el mismo salario (42). Aquí está la respuesta incorrecta:
mean(salary[!duplicated(salary)])## [1] 45
La función llamada rle, que significa ‘codificación de longitud de ejecución’ se entiende más fácilmente con un ejemplo. Aquí hay un vector de 150 números aleatorios de una distribución de Poisson con media 0.7:
(poisson<- rpois(150, 0.7))## [1] 0 0 0 1 0 1 0 1 1 0 0 0 0 0 0 1 0 0 1 0 2 2 0 0 1 1 1 0 0 1 1 3 3 0 1 0 1
## [38] 0 3 2 0 0 2 1 0 1 0 1 1 1 1 0 0 1 0 2 1 2 0 0 1 1 0 0 0 0 0 1 1 0 0 0 0 0
## [75] 1 1 0 1 1 0 0 0 1 2 0 0 0 0 1 1 0 1 0 0 1 0 1 1 2 0 1 0 1 1 1 0 1 0 0 0 1
## [112] 2 0 0 0 1 0 1 0 0 0 1 0 0 0 0 0 0 1 0 1 0 0 0 1 1 0 1 0 1 1 1 0 1 1 0 0 1
## [149] 3 0
Podemos hacer nuestra propia codificación de longitud de ejecución en el vector a ojo: hay una ejecución de dos 1s, luego una ejecución de dos 0s, luego un solo 2, luego un solo 1, luego un solo 0, y así sucesivamente. Así que las longitudes de carrera son 2, 1, 2, 1, 3, 1,…. Los valores asociados a estas ejecuciones fueron 0, 1, 0, 1, 0, 1,…. Aquí está la salida de rle:
rle(poisson)## Run Length Encoding
## lengths: int [1:88] 3 1 1 1 1 2 6 1 2 1 ...
## values : int [1:88] 0 1 0 1 0 1 0 1 0 1 ...
El objeto producido por r es una lista de dos vectores: las longitudes de las corridas y los valores que hicieron la ejecución.
Para encontrar la ejecución más larga y el valor asociado con esa ejecución más larga, usamos las listas indexadas de esta manera:
max(rle(poisson)[[1]])## [1] 6
Así que la carrera más larga en este vector de números fue 6. ¿Pero 6 de qué? Utilizamos which para encontrar la ubicación de la 6 en longitudes, luego aplique este índice a los valores para encontrar la respuesta
which(rle(poisson)[[1]]==6)## [1] 7 73
rle(poisson)[[2]][67]## [1] 0
Por lo tanto, no es sorprendente dado que la media fue de solo 0.7, la carrera más larga fue de ceros. Aquí hay una función para devolver la longitud de la ejecución y su valor para cualquier vector:
run.and.value<- function(x){
a<- max(rle(poisson)[[1]])
b<- rle(poisson)[[2]][which(rle(poisson)[[1]] == a)]
cat("length= ",a," value= ",b, "\n")}Probando la función en el vector de 150 datos de Poisson se obtiene:
run.and.value(poisson)## length= 6 value= 0 0
A veces es interesante conocer el número de ejecuciones en un vector dado (por ejemplo, cuanto menor sea el número de corridas, cuanto más agregados sean los números; y cuanto mayor sea el número de carreras, más regularmente se espacia). Usamos la función length para esto:
length(rle(poisson)[[2]])## [1] 88
indicando que los 150 valores se organizaron en 93 corridas (este es un valor intermedio, característico de un patrón aleatorio). El valor 93 aparece entre corchetes [1:93] en la salida de la codificación de longitud de ejecución función. En un ejemplo diferente, supongamos que tuviéramos valores n1 de 1 que representan ‘presente’ y n2 valores de 0 que representan «ausente»; Entonces el número mínimo de carreras sería 2 (un bloque sólido de 1s y luego un bloque vendido de 0s). El número máximo de corridas sería 2n + 1 si se alternaran (hasta el número menor n = min (n1, n2) se acabó). Aquí hay una prueba de ejecución simple basada en 1000 aleatorizaciones de 25 unos y 30 ceros:
n1<-25
n2<-30
y<-c(rep(1,n1),rep(0,n2))
len<-numeric(10000)
for (i in 1:1000)len[i]<-length(rle(sample(y))[[2]])
quantile(len,c(0.025,0.975))## 2.5% 97.5%
## 0 31
Por lo tanto, para estos datos (n1 = 25 y n2 = 30) un patrón agregado obtendría una puntuación de 0 carreras, y un patrón regular anotaría 31 o más carreras. Cualquier puntuación entre 0 y 31 cae dentro del ámbito del azar patrones.
Hay tres funciones esenciales para manipular conjuntos. Los principios son fáciles de ver si trabajamos con un ejemplo de dos conjuntos:
setA <- c("a", "b", "c", "d", "e") setB <- c("d", "e", "f", "g")Tome nota mental de lo que los dos conjuntos tienen en común y lo que es único para cada uno. La unión de dos conjuntos es todo en los dos conjuntos tomados juntos, pero contando elementos solo una vez que son comunes a ambos conjuntos:
union(setA, setB)## [1] "a" "b" "c" "d" "e" "f" "g"
La intersección de dos conjuntos es el material que tienen en común:
intersect(setA, setB)## [1] "d" "e"
Tenga en cuenta, sin embargo, que la diferencia entre dos conjuntos depende del orden. Es el material que está en el primer conjunto con nombre, que no está en el segundo conjunto con nombre. Por lo tanto, setdiff(A,B) da una respuesta diferente que setdiff(B,A). Para nuestro ejemplo:
setdiff(setA, setB)## [1] "a" "b" "c"
setdiff(setB, setA)## [1] "f" "g"
Por lo tanto, debería darse el caso de que setdiff(setA,setB) más intersect(setA,setB) más setdiff(setB,setA) es lo mismo que la union de los dos conjuntos. Vamos a comprobar:
all(c(setdiff(setA, setB), intersect(setA, setB), setdiff(setB, setA))== union(setA, setB))## [1] TRUE
También hay una función incorporada setequal para probar si dos conjuntos son iguales:
setequal(c(setdiff(setA, setB), intersect(setA, setB),setdiff(setB, setA)), union(setA, setB))## [1] TRUE
Puede utilizar %in% para comparar conjuntos. El resultado es un vector lógico cuya longitud coincide con el vector en la izquierda:
setA %in% setB## [1] FALSE FALSE FALSE TRUE TRUE
setB %in% setA## [1] TRUE TRUE FALSE FALSE
Usando estos vectores de valores lógicos como subíndices, podemos demostrar, por ejemplo, que setA[setA %in% setB] es lo mismo que intersect(setA,setB)
setA[setA %in% setB]## [1] "d" "e"
intersect(setA, setB)## [1] "d" "e"