Mostrando entradas con la etiqueta Vector. Mostrar todas las entradas
Mostrando entradas con la etiqueta Vector. Mostrar todas las entradas

jueves, 26 de diciembre de 2024

Lenguajes. R.

Subconjuntos de un vector

Por diversos motivos, es posible y frecuente que necesitemos trabajar con un subconjuntos de los datos que contiene un vector; para ello necesitamos procedimientos que nos permitan acceder a esos datos. En las dos entradas anteriores ya nos encontramos con situaciones en las que esta temática estaba presente, pero no de forma explícita, por lo que necesitamos abordarla en la actual.



De las diferentes opciones disponibles para la obtención de subconjuntos, el uso de índices es el único que podemos emplear con los vectores, y con ciertas restricciones, como tendremos ocasión de ver aquí.

El índice es un numeral que indica la posición de cada elemento en la colección de datos (en este caso, en el vector) (1), de modo que es posible acceder a cada uno de sus datos empleando el índice (num[1]), u omitirlo también usando el índice como identificador (num[-1]) (2), como tuvimos ocasión de comprobar en una [anterior ocasión].

En realidad poco vamos a añadir en esta entrada a lo ya visto, pero sí interesa tratar el tema de forma específica por la funcionalidad que presenta para el tratamiento de datos.

Supongamos que tenemos un vector con los identificadores de los cursos de E. Primaria (curso<-c("P1","P2","P3","P4","P5","P6")) a partir del cual deseamos crear varios vectores derivados:
  • Un vector con el curso P3 -> curso3 <- curso[3] devuelve "P3"
  • Otro con los tres primeros cursos -> curso13 <- curso[1:3] devuelve "P1" "P2" "P3"
  • Otro con los cursos impares -> cursosimp <- curso[c(1,3,5)]) devuelve "P1" "P3" "P5"
  • Y otro sin los dos cursos finales -> curosinic <- curso[-c(5,6)] devuelve "P1" "P2" "P3" "P4"
Como puedes ver, para obtener un elemento o varios consecutivos empleamos la fórmula vector[Indice/s], estableciendo un intervalo en caso de desear recuperar ese intervalo de elementos, pero cuando deseamos obtener un sub-vector formado por elementos no consecutivos debemos emplear la función c() enmarcada dentro de la estructura básica (vector[c(indices)]); sólo así es posible utilizar la separación de índices mediante coma, que es la forma de hacer referencia a cada índice individual) (3)

Salvo por esta limitación interpretativa, el modo de obtener subconjunto del conjunto vector mediante índices es muy simple, lo que nos permite generar con facilidad subconjuntos de datos a partir del contenido del vector.


NOTAS

(1) Recuerda que en R el índice no se inicia en 0, sino en 1. En num <- c("casa","mesa"), el elemento 1 (índice 1) es "casa". En OOo Basic "casa" ocuparía la posición (índice) 0.
(2) La diferencia entre ambas instrucciones es que la primera nos devuelve el dato ubicado en la posición que concreta el índice, mientras que la segunda devuelve todos los datos contenidos en el vector menos el indicado por su índice (en este caso el que ocupa la posición 1)
(3) Si empleáramos la separación de índices mediante coma pero son la función c(), R nos devolvería error, ya que interpreta que estamos solicitando datos de una estructura n-dimensional, y un vector sólo tiene una dimensión (longitud). El signo - es substractivo, de ahí que al anteponerlo a la función c() (-c(5,6)) obtengamos como resultado los elementos del vector menos los indicados como argumentos de dicha función.

Lenguajes. R.

Vectorización

La vectorización consiste en la capacidad que tiene R de aplicar determinadas operaciones a todos los elementos de un vector de forma directa. Esta capacidad ejemplifica nuevamente el carácter de datos básico que tiene el vector en este lenguaje.


Gracias a la vectorización es posible generar operaciones simples o complejas cuyo resultado afecte a todos los componentes del vector. Los operadores admitidos son los operadores aritméticos y los relacionales.

Para num1 <- c(2,4,6,8,10,12)
num1 * 2  devuelve  4 8 12 16 20 24
num1 < 5 devuelve TRUE TRUE FALSE FALSE FALSE FALSE

Pensando en operaciones aritméticas, podemos calcular fácilmente el porcentaje de todos los elementos de un vector o convertir la puntuación directa en puntuación típica de forma muy sencilla. Con los operadores relacionales, podemos valorar una determinada expresión comparativa, diferenciando qué componentes del vector la cumplen y cuáles no, también de forma rápida y sencilla.

También aquí rige lo dicho en la entrada anterior sobre la sustracción de elementos del vector: se trata de un proceso que no altera la composición del vector original, por lo que si nos interesa conservar el resultado de la operación deberemos asignar dicha operación a un segundo vector. Por ejemplo, para el vector num1 anterior...

numdoble <- num1 * 2

num1 devuelve porque conserva  2,4,6,8,10,12

numdoble devuelve  (y conserva)  4 8 12 16 20 24

 

Lenguajes. R.

Vectores. Definición.

Un vector es la colección de datos más sencilla con la que trabaja R. Es unidimensional y contiene datos del mismo tipo, aunque puede constar de metadados que describen los datos que contiene (1).


R es un lenguaje vectorizado, lo que quiere decir que se puede considerar al vector como un tipo básico de datos en este lenguaje; algo que es coherente con el objetivo para el que fue pensado como lenguaje. De hecho, y a la inversa, se puede considerar cualquier variable como un vector de un único dato (2)

Para crear un vector usaremos la función c() (concatenar) (3) y el operador de asignación, por ejemplo:
  • num <- c(1,3,5,7)
  • pal <- c("mesa","silla","cama")
Si lo que necesitamos es crear un vector de números consecutivos podemos hacerlo de este modo: num <- 1:10, que crea un vector con los números 1...10 de forma directa (4)

En R es muy sencillo añadir elementos a un sector ya creado (5), siendo suficiente con reutilizar el vector previamente creado de forma recursiva:
  • num <- c(1,3,5,7)
  • num <- c(num,9)
En este caso añadimos al final del vector num un nuevo dato (9), pero podríamos añadirlo al inicio o añadir más de un dato usando el mismo procedimiento, pero variando la posición o la cantidad de dados. Del mismo modo, podemos crear vectores de vectores (numc <- c(numa,numb)), operación que realizaremos con frecuencia (6).

Al añadir un dato a un vector o al crear un vector de vectores, se puede dar el caso que el tipo de dato no sea el mismos, lo que aparentemente es una contradicción con el criterio de que un vector contiene datos del mismo tipo. Este problema se resuelve en R de forma automática mediante el mecanismo de coerción (7)

Para ver el contenido de un vector es suficiente con escribir su nombre y pulsar intro; y si queremos acceder a un elemento en concreto escribiremos el nombre del vector y su id entre corchetes (num[1]) y pulsamos intro (8). El mismo resultado obtendremos si utilizamos la función print(), pasando como argumento el nombre del vector (print(num)), en el primer caso, y la expresión num[1] en el segundo.

El acceso a un elemento del vector nos permite generar variables a partir del vector por el simple procedimiento de asignación del componente a la variable (num2 <- num[1]) (9)

Si queremos eliminar un elemento (o varios) de un vector (10), o crear un subvector a partir del original menos determinado/s elemento/s, es suficiente con añadir el signo - al índice de posición del elemento (num[-1]) o a la función c() (num[-c(1)]). Esta sustracción sólo elimina el elemento en el momento en que se ejecuta, pero no altera la composición original del vector, así que si lo que necesitamos es un nuevo vector que no cuente con esos elementos, deberemos asociar la operación anterior a la creación de dicho subvector (numB <- num[-1]).


NOTAS

(1) El tema de los metadados supera los objetivos de este blog, por lo que no será tratado. No obstante es una cuestión de un alto nivel de complejidad, por lo que es frecuente trabajar con vectores sin hacer referencia a sus metadatos.
(2) Si, por ejemplo, utilizamos la función is.vector(3), nos devolverá TRUE, y si solicitamos información sobre su longitud (length(3)) nos devolverá 1. Esto implica que R está tratando el dato 3 como vector. Lo mismo sucederá si asociamos este dato a una variable (num <- 3) y la usamos como argumento de ambas funciones.
(3) También podemos usar las funciones rep() y seq(), que permiten crear patrones.
(4) Esta formulación admite también números decimales y negativos, así como orden inverso.
(5) Lo que contrasta con la complejidad que presenta esta operación en OOo Basic y ejemplifica de nuevo la orientación de R al análisis de datos.
(6) En el supuesto de que numa <- c(1,2) y numb <- c(3,4), numc estaría formado por 1,2,3,4
(7) Conversión implícita de un tipo de dato a otro más flexible. Por ejemplo, si añadimos "once" al vector num (num <- c(num,"once")), todos los datos se convierten a tipo character. De la coerción ya hablamos [en esta entrada]
(8) La identificación de los componentes de los vectores no empiezan en 0, como sí ocurre en otros lenguajes, así que num[1] no devuelve el primer dato que contiene el vector.
(9) De hecho, una variable puede ser considerada como un vector de un único dato.
(10) Por lo que se precisa más adelante, es posible que en vez de decir "eliminar", debería decirse "visualizar el vector sin determinados elementos", ya que no se produce tal eliminación de datos del vector original.