Sexta sesión con Rcmdr: más sobre vectores y combinatoria.

Cualquier curso de introducción a la Estadística incluye, a su vez, una introducción a la Probabilidad. Y los ejemplos iniciales de cálculo de probabilidades recurren necesariamente (por simplicidad, y por razones históricas) a juegos de azar, como los dados, lanzamientos de monedas, loterías, ruletas, etc. Estas situaciones simplificadas, e idealizadas, sirven de modelo a muchas otras que encontramos después en aplicaciones “más serias”. Y en muchas de ellas juega un papel la Regla de Laplace, que en esencia dice que, en un experimento en el que hay una familia de sucesos elementales equiprobables (SEE), la probabilidad del suceso A es:

P(A)=\dfrac{\mbox{n\'umero de SEE en los que ocurre A}}{\mbox{n\'umero total de SEE posibles}}

Para utilizar esta regla efizcamente hay que contar los sucesos que cumplen una cierta condición. Y contar, por elemental que pueda parecer, es una actividad extremadamente complicada. La rama de las matemáticas que se encarga de este tipo de problemas es la Combinatoria. Y en esta entrada vamos a empezar a utilizar la combinatoria como excusa para aprender un poco más sobre cómo se fabrican vectores a medida con R, y a mejorar nuestras habilidades con esos vectores.

Fabricando vectores a medida

Ya sabemos que, en R, podemos crear un vector con la función c, simplemente  enumerando sus elementos, como en

unVector=c(2,7,2,3,1,5)

Esto está muy bien, pero si queremos fabricar así un vector que contenga los números del 1 al 1000, es muy probable que antes de acabar nos invada la melancolía (por no mencionar el hecho de que, casi con seguridad, cometeremos algún error). Afortunadamente, R dispone de mecanismos para simplificar este tipo de tareas repetitivas. En este ejemplo, basta con usar:

milNumeros=1:1000
milNumeros

La segunda líneas, ya lo sabemos, es para ver el resultado. Y se obtiene:

(Por cierto, el resultado puede servir para entender porque R no muestra ningún resultado a menos que se lo pidamos explícitamente).

Es un avance sin duda, pero aún no resuelve muchos problemas. ¿Y si queremos los números del 1 al 1000, pero saltando de tres en tres? El lector mañoso tal vez habrá pensado “hago un vector con los primeros 333, y lo multiplico por 3…”. Pero en R hay una manera mucho más sencilla, usando la función seq. Hacemos:

deTresEnTres=seq(1,1000,3)
deTresEnTres

Y ahora la salida es:exactamente lo que queríamos.

La función seq permite fabricar vectores cuyos elementos se diferencian en una cantidad fija; que puede ser cualquier número, entero, fraccionario, expresado con decimales, etc.  Hay otra función, la función rep, estrechamente emparentada con est, cuyo principal uso es fabricar vectores siguiendo un patrón. El nombre rep viene de repeat, repetir. Y eso ayuda a adivinar lo que sucede si escribimos estos comandos:

datos=c(1,2,3,4,5)
rep(datos,3)

La salida correspondiente es, como cabría esperar, el vector datos repetido tres veces:

> datos=c(1,2,3,4,5)
> rep(datos,3)
[1] 1 2 3 4 5 1 2 3 4 5 1 2 3 4 5

Quizá no sea tan fácil adivinar lo que sucede con este otro comando:

datos=c(1,2,3,4,5)
rep(datos,c(2,9,1,4,3))

Si lo ejecutamos,  la salida es:

> datos=c(1,2,3,4,5)
> rep(datos,c(2,9,1,4,3))
[1] 1 1 2 2 2 2 2 2 2 2 2 3 4 4 4 4 5 5 5

Y ahora está más claro lo que sucede: el segundo argumento nos dice cuántas veces debemos repetir cada uno de los correspondientes elementos del vector datos (el primer argumento).

Este funcionamiento de rep es especialmente interesante cuando tenemos una tabla de frecuencias.  Todavía no hemos visto, en este blog, como crear tablas en R (aunque nos hemos encontrado con las primeras al hacer Estadística Descriptiva). Pero vamos a suponer que tenemos dos vectores:

valores=c(2,3,5,8,13)
frecuencias=c(5,7,12,2,14)

de manera que el primero contiene los valores (distintos) que aparecen en nuestros datos, y el segundo contiene las frecuencias de esos valores (por supuesto, los dos vectores tendrán la misma longitud). Entonces , para recuperar el conjunto inicial de datos (sin agrupar) partiendo de esta “tabla de frecuencias”, podemos usar así la función rep:

valores=c(2,3,5,8,13)
frecuencias=c(5,7,12,2,14)
datosSinAgrupar=rep(valores,frecuencias)
datosSinAgrupar

Y se obtiene este resultado:

> valores=c(2,3,5,8,13)
> frecuencias=c(5,7,12,2,14)
> datosSinAgrupar=rep(valores,frecuencias)
> datosSinAgrupar
[1]  2  2  2  2  2  3  3  3  3  3  3  3  5  5  5  5  5  5  5  5  5  5  5  5  8  8 13 13
[29] 13 13 13 13 13 13 13 13 13 13 13 13

(Recuerda que la colocación del vector salida depende de la anchura de tu ventana de Rcmdr. Aquí aparecen [1] y [29], pero en tu máquina aparecerán seguramente otros valores, o sólo uno de ellos.)

Finalmente, si lo que queremos es ordenar un vector de números, la función sort viene en nuestra ayuda. Por ejemplo, el resultado de estos comandos:

datos=c(12,13,93,4,42,77,24,15,79,49,20,70,46,33,10,15,62,48,56,88,74,68,8,83,94,48,95,61,15,32)
sort(datos)

es este, en el que aparece el vector ordenado:

> datos=c(12,13,93,4,42,77,24,15,79,49,20,70,46,33,10,15,62,48,56,88,74,68,8,83,94,48,95,61,15,32)
> sort(datos)
[1]  4  8 10 12 13 15 15 15 20 24 32 33 42 46 48 48 49 56 61 62 68 70 74 77 79 83 88 93 94 95

Una aclaración importante. Esta ordenación no afecta en absoluto al vector datos original. Si quieres ordenar el vector y guardar el vector ordenado con el mismo nombre, entonces puedes usar el comando

datos = sort(datos)

pero es importante entender que este es un viaje sin retorno: el vector datos original, sin ordenar, se habrá perdido, y sólo tendremos la versión ordenada. ¡Cuidado con la posible pérdida de información!

Lanzando los dados: la función sample

Disponer de ordenadores, que hacen el trabajo duro por nosotros,  nos permite realizar muchos experimentos en los que poner a prueba nuestras ideas . En los primeros pasos dentro del mundo de la probabilidad, pensamos a menudo en ejemplos que involucran el lanzamiento de un dado.¿Cómo podemos usar R para “lanzar un dado virtual”? La forma más sencilla de hacerlo es utilizar otra función que fabrica vectores, la función sample.El código que usa esta función para simular 100 lanzamientos de un dado es este:

sample(1:6,100,replace=TRUE)

Los tres argumentos de la función sample, en este ejemplo simple, son:

  • el rango de resultados deseados. Por ejemplo, para un dado, del 1 al 6.
  • el número de valores que queremos obtener. Es decir, cuántas veces tiramos el dado, que aquí son 100.
  • en principio, R no admite repeticiones de valores que ya han aparecido (son muestras sin remplazamiento). Si queremos valores repetidos (remplazamiento), debemos indicarlo con el argumento replace=TRUE.

Y el resultado es algo como esto:

> sample(1:6,100,replace=TRUE)
[1] 1 3 1 6 4 6 5 5 5 4 2 2 1 1 4 5 1 3 3 6 1 2 6 6 6 6 1 2 2 5 5 2 3 5 1 2 6 4 6 1 6 2 4 2 5 5 4 1
[49] 3 1 6 5 4 5 5 3 5 2 4 2 6 6 3 3 1 1 1 1 2 1 2 6 4 4 3 5 4 1 3 1 1 3 5 3 6 2 4 6 5 1 5 6 2 3 5 5
[97] 6 3 5 4

En tu máquina los números serán distintos, claro está, porque la función sample está eligiendo aleatoriamente los valores (y en este caso, todos son equiprobables).

Si quieres saber cuántas veces ha aparecido cada uno de los valores, puedes utilizar

unDadoCienVeces=sample(1:6,100,replace=TRUE)
table(unDadoCienVeces)

Le hemos dado un nombre al vector para facilitar las cosas, y para que puedas hacer un experimento: en lugar de 100, escribe 100000, y compara las frecuencias con las anteriores. Además, si no le pusiéramos nombre, al ejecutar el comando verías desfilar ante tus ojos 100000 números en la ventana de resultados…

La función sample permite hacer ajustes mucho más finos que los que hemos visto en este primer ejemplo. Volveremos sobre esto en próximas entradas, pero por el momento nos despedimos de ella con un ejemplo que pretende preparar el terreno y avivar la curiosidad. Ejecuta unas cuantas veces este comando, observa los resultados  y trata de adivinar lo que está pasando (como pista, prob viene de probabilidad):

sample(c(1,2,4,7),100,prob=c(0.2,0.1,0.1,0.6),replace=TRUE)

Seleccionando elementos de vectores

Hemos lanzado 100 veces un dado, y hemos hecho la tabla de frecuencias del vector unDadoCienVeces resultante de ese experimento. Eso nos permite saber cuántas veces ha aparecido, por ejemplo, el número 5. Pero no nos permite saber cuál fue el resultado precisamente en la tirada número 23.  Para averiguar esto, en R escribimos

unDadoCienVeces[23]

De esa forma, usando los corchetes, podemos acceder directamente a cualquier posición del vector. Por ejemplo, el primer y el último elemento del vector son:

unDadoCienVeces[1]
unDadoCienVeces[length(unDadoCienVeces)]

En este caso sabemos que el vector tiene 100 elementos, y para obtener el último elemento podríamos haber escrito

unDadoCienVeces[100]

pero la otra versión (usando length) tiene la ventaja de que seguirá funcionando aunque el vector cambie.

Este recurso de los corchetes es mucho más potente de lo que parece a primera vista. Podemos seleccionar varios elementos a la vez indicando sus posiciones. Para seleccionar los elementos de unDadoCienVeces en las posiciones de la 12 a la 27 hacemos:

unDadoCienVeces[12:27]

y obtenemos un vector con los números que ocupan exactamente esas posiciones. Y si las posiciones que queremos no son consecutivas, basta con indicarlas mediante un vector:

unDadoCienVeces[c(3,8,21,43,56)]

nos proporciona los elementos en esas posiciones del vector. Cuando se combina esto con otras ideas que estamos viendo en esta entrada del blog se pueden conseguir resultados muy útiles. Por ejemplo, ¿qué crees que sucede al hacer esto? (Haz el experimento).

datos=1:100
datos
datos[seq(1,length(datos),3)]

Pero aún podemos ir más lejos. Podemos utilizarlo para seleccionar los elementos del vector que cumplen cierta condición. Por ejemplo, queremos saber cuántos de los resultados en unDadoCienVeces son mayores que 3. En primer lugar, igual que aprendimos (en la segunda sesión con Rcmdr) a sumar una cantidad a un vector, o a elevar un vector al cuadrado, etc., podemos también aplicar una condición lógica, como una desigualdad, a un vector:

unDadoCienVeces > 3

(Añado espacios por claridad; no cambia nada, los añadas o no). La respuesta es un nuevo vector como este (te recuerdo que en tu caso los resultados concretos variarán):

> unDadoCienVeces > 3
[1] FALSE  TRUE FALSE FALSE FALSE FALSE  TRUE  TRUE  TRUE  TRUE  TRUE FALSE FALSE  TRUE  TRUE  TRUE  TRUE FALSE  TRUE  TRUE  TRUE  TRUE FALSE FALSE FALSE FALSE FALSE FALSE FALSE  TRUE FALSE FALSE FALSE FALSE FALSE FALSE  TRUE  TRUE
[39] FALSE  TRUE  TRUE  TRUE  TRUE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE  TRUE FALSE  TRUE  TRUE FALSE  TRUE  TRUE  TRUE FALSE FALSE  TRUE  TRUE FALSE FALSE FALSE  TRUE  TRUE FALSE FALSE FALSE FALSE FALSE FALSE  TRUE FALSE
[77]  TRUE  TRUE  TRUE  TRUE FALSE  TRUE  TRUE  TRUE  TRUE  TRUE FALSE  TRUE FALSE FALSE FALSE  TRUE FALSE FALSE FALSE FALSE FALSE FALSE  TRUE  TRUE

Cada posición de este vector nos indica si la condición (o suceso) “ser mayor que 3” se cumple en la correspondiente posición del vector unDadoCienVeces. Si lo que queremos es obtener los valores originales del vector, entonces combinamos esta idea con la selección por corchetes:

unDadoCienVeces[ unDadoCienVeces > 3 ]

Y obtendremos una salida parecida a esta

> unDadoCienVeces[ unDadoCienVeces > 3 ]
[1] 6 5 6 6 5 5 4 6 5 4 6 4 6 4 5 5 4 4 5 5 6 4 4 4 4 4 5 4 6 5 5 5 6 4 5 6 5 4 4 5 5 5 5 5 6

con un vector en el que se ha seleccionado todos los elementos (y sólo esos elementos) del vector unDadoCienVeces que cumplen la condición “ser mayor que 3”.

Resumen final

Digerir esta entrada, en la que hemos visto muchos conceptos nuevos, puede llevar algo de tiempo y requiere de un rato de práctica con R. Haz todos los experimentos que quieras: son gratis y no vas a romper nada, claro. Con las técnicas que hemos aprendido, podemos dar los primeros pasos en el mundo de la probabilidad. Pero todavía, si queremos hacer un experimento tan sencillo como lanzar dos dados a la vez, y repetirlo 1000 veces, no disponemos del lenguaje necesario para representar esto en R de la forma más eficaz. Trataremos ese tema en la próxima sesión, en la que conoceremos las tablas de R (ya las hemos intuido, al pedirle a R que haga tablas de frecuencias).

Gracias por la atención.

2 pensamientos en “Sexta sesión con Rcmdr: más sobre vectores y combinatoria.

  1. Pingback: Octava sesión con Rcmdr. Datos cualitativos. Matrices y dataframes. | PostData

  2. Pingback: Novena sesión con Rcmdr: variables aleatorias discretas en R. Sampleando en R. | PostData

Responder

Introduce tus datos o haz clic en un icono para iniciar sesión:

Logo de WordPress.com

Estás comentando usando tu cuenta de WordPress.com. Cerrar sesión /  Cambiar )

Google photo

Estás comentando usando tu cuenta de Google. Cerrar sesión /  Cambiar )

Imagen de Twitter

Estás comentando usando tu cuenta de Twitter. Cerrar sesión /  Cambiar )

Foto de Facebook

Estás comentando usando tu cuenta de Facebook. Cerrar sesión /  Cambiar )

Conectando a %s