Saltar al contenido principal
LibreTexts Español

3.6: Marcos de datos

  • Page ID
    55126
  • \( \newcommand{\vecs}[1]{\overset { \scriptstyle \rightharpoonup} {\mathbf{#1}} } \) \( \newcommand{\vecd}[1]{\overset{-\!-\!\rightharpoonup}{\vphantom{a}\smash {#1}}} \)\(\newcommand{\id}{\mathrm{id}}\) \( \newcommand{\Span}{\mathrm{span}}\) \( \newcommand{\kernel}{\mathrm{null}\,}\) \( \newcommand{\range}{\mathrm{range}\,}\) \( \newcommand{\RealPart}{\mathrm{Re}}\) \( \newcommand{\ImaginaryPart}{\mathrm{Im}}\) \( \newcommand{\Argument}{\mathrm{Arg}}\) \( \newcommand{\norm}[1]{\| #1 \|}\) \( \newcommand{\inner}[2]{\langle #1, #2 \rangle}\) \( \newcommand{\Span}{\mathrm{span}}\) \(\newcommand{\id}{\mathrm{id}}\) \( \newcommand{\Span}{\mathrm{span}}\) \( \newcommand{\kernel}{\mathrm{null}\,}\) \( \newcommand{\range}{\mathrm{range}\,}\) \( \newcommand{\RealPart}{\mathrm{Re}}\) \( \newcommand{\ImaginaryPart}{\mathrm{Im}}\) \( \newcommand{\Argument}{\mathrm{Arg}}\) \( \newcommand{\norm}[1]{\| #1 \|}\) \( \newcommand{\inner}[2]{\langle #1, #2 \rangle}\) \( \newcommand{\Span}{\mathrm{span}}\)\(\newcommand{\AA}{\unicode[.8,0]{x212B}}\)

    En el capítulo 28, “Vectores”, presentamos brevemente los marcos de datos como tablas de almacenamiento de datos. Ahora que tenemos una comprensión clara tanto de los vectores como de las listas, podemos describir fácilmente los marcos de datos. (Si te saltaste apresuradamente los capítulos 28 y 30 para aprender sobre los marcos de datos, ¡ahora es el momento de volver a ellos!) Los marcos de datos son esencialmente listas nombradas, donde los elementos son vectores que representan columnas. Pero los marcos de datos proporcionan algunas características más que simples listas de vectores. Aseguran que los vectores de columna componente sean siempre de la misma longitud, y nos permiten trabajar con los datos por fila así como por columna. Los marcos de datos son algunos de los tipos de datos más útiles y ubicuos en R.

    Si bien ya hemos cubierto el uso de la función read.table () para producir un marco de datos basado en el contenido de un archivo de texto, también es posible crear un marco de datos a partir de un conjunto de vectores.

    III.6_1_R_111_DF_desde_rasguño
    alt

    Cuando se imprimen, el contenido de los vectores de columna se muestra cuidadosamente, con los nombres de las columnas a lo largo de la parte superior y los nombres de fila a lo largo del lado izquierdo

    Al igual que con read.table (), la función data.frame () toma un argumento opcional StringSasFactors, que especifica si los vectores de caracteres (como ids) deben convertirse a tipos de factores (los cubriremos en detalle más adelante). Por ahora, deshabilitaremos esta conversión.

    Ejecutar str (gene_info) revela la naturaleza de lista del marco de datos:

    III.6_3_R_113_DF_desde_Scratch_str

    Al igual que elementos de listas, las columnas de marcos de datos no tienen que tener nombres, pero no tenerlos es poco común. La mayoría de los marcos de datos obtienen nombres de columna cuando se crean (ya sea por read.table () o data.frame ()), y si se desestablecen, generalmente son V1, V2, y así sucesivamente. Los nombres de las columnas se pueden acceder y establecer con la función names (), o con la función colnames () más apropiada.

    III.6_4_R_114_DF_Colnames

    Para resaltar la naturaleza tipo lista de los marcos de datos, podemos trabajar con marcos de datos por columna de manera muy similar a listas por elemento. Las tres líneas del siguiente ejemplo dan como resultado que sub_info sea un marco de datos de dos columnas.

    III.6_5_R_115_DF_extracto_cols

    Por lo tanto, una expresión como gene_info [2] no devolvería un vector numérico de longitudes, sino un marco de datos de una sola columna que contiene el vector numérico. Podemos usar la sintaxis [[]] y la sintaxis $ para referirnos también a los vectores contenidos dentro de los marcos de datos (este último es mucho más común).

    III.6_6_R_116_DF_EXTRACT_COL_ELEMENTS

    Incluso podemos eliminar columnas de un marco de datos estableciendo el elemento en NULL, como en gene_info$length <- NULL.

    El verdadero encanto de los marcos de datos es que podemos extraer y de otra manera trabajar con ellos por fila. Así como los marcos de datos tienen nombres de columna, también tienen nombres de fila: un vector de caracteres de la misma longitud que cada columna. Desafortunadamente, por defecto, los nombres de fila son “1", “2", “3", y así sucesivamente, pero cuando se imprime el marco de datos, se dejan las comillas (ver el resultado de print (gene_info) arriba). Los nombres de fila son accesibles a través de la función rownames ().

    Los marcos de datos son indexables usando una sintaxis extendida []: [,] <row_selector><column_selector>, donde <row_selector>y <column_selector>son vectores. Al igual que con los vectores y listas, estos vectores de indexación/selección pueden ser enteros (para seleccionar por índice), caracteres (para seleccionar por nombre) o lógicos (para seleccionar lógicamente). También al igual que con los vectores, al indexar por posición de índice o nombre, se respeta el orden solicitado.

    III.6_7_R_117_DF_Row_Col_Selection

    Aquí está el resultado resultante, ilustrando que “3" y “1" eran los nombres de las filas, que ahora aparecen en la primera y segunda fila, respectivamente. [1]

    III.6_8_R_118_DF_Row_Col_Selection

    Si encuentra esto confuso, considere qué pasaría si primero asignáramos los nombres de fila del marco de datos original a algo más razonable, antes de la extracción.

    III.6_9_R_119_DF_Better_Row_Names

    Ahora, cuando se imprimen, se revela la naturaleza de carácter de los nombres de las filas.

    III.6_10_R_120_DF_Better_Row_Nombres_Imprimir

    Finalmente, si uno de <row_selector>o <column_selector>no se especifica, entonces se incluyen todas las filas o columnas. Como ejemplo, gene_info [c (3,1),] devuelve un marco de datos con la tercera y primera filas y las tres columnas, mientras que gene_info [, c (“longitudes”, “ids”)] devuelve una con solo las columnas “longitudes” e “ids”, pero todas las filas.

    Operaciones de marco de datos

    Debido a que los marcos de datos tienen mucho en común con las listas y filas, y las columnas se pueden indexar por número de índice, nombre o vector lógico, hay muchas formas poderosas de manipularlos. Supongamos que queríamos extraer solo aquellas filas donde la columna de longitudes es menor que 200, o la columna gcs es menor que 0.3.

    III.6_11_R_121_DF_Selección_lógica

    Esta sintaxis es concisa pero sofisticada. Mientras que gene_info$length se refiere al vector numérico llamado “longitudes” en el marco de datos, el operador lógico < se vectoriza, reciclándose el elemento único 200 según sea necesario. El mismo proceso ocurre para gene_info$gcs < 0.3, y el operador lógico-or | es vectorizado, produciendo un vector lógico usado posteriormente para seleccionar las filas de interés. Se seleccionaría una versión aún más corta de estas dos líneas <- gene_info [gene_info$longitudes < 200 | gene_info$gcs < 0.3,]. La salida impresa:

    III.6_12_R_121_DF_Lógical_Selección_Imprimir

    Si quisiéramos extraer el vector gcs de este resultado, podríamos usar algo como selected_gcs <- selected$gcs. A veces se utiliza una sintaxis más compacta, donde el $ y el nombre de la columna se anexan directamente a la sintaxis [].

    III.6_13_submarco_columna_1

    Alternativamente, y quizás más claramente, primero podemos usar la notación $ para extraer la columna de interés, y luego usar [] indexación lógica en el vector resultante.

    III.6_14_submarco_columna_2

    Debido a que subestablecer filas de marcos de datos por condición lógica es tan común, hay una función especializada para esta tarea: subset (). El primer parámetro es el marco de datos desde el que seleccionar, y los parámetros posteriores son expresiones lógicas basadas en nombres de columna dentro de ese marco de datos (se dejan comillas). Por ejemplo, seleccionado <- subconjunto (gene_info, longitudes < 200 | gcs < 0.3). Si se da más de una expresión lógica, se combinan con & (y). Así subconjunto (gene_info, longitudes < 200, gcs < 0.3) es equivalente a gene_info [gene_info$longitudes < 200 & gene_info$gcs < 0.3,].

    Si bien la función subset () es conveniente para extracciones simples, conocer los entresijos de [] la selección de marcos de datos en lo que se refiere a listas y vectores es una herramienta poderosa. Considere la función order (), que, dado un vector, devuelve un vector índice que se puede utilizar para ordenar. Al igual que con el uso de order () para ordenar un vector, podemos usar order () para ordenar un marco de datos basado en una columna en particular.

    III.6_15_R_122_DF_ORDERING

    El resultado es un marco de datos ordenado por la columna de longitudes:

    III.6_16_R_123_DF_Pedido_Salida

    Debido a que los marcos de datos obligan a todos los vectores de columna a tener la misma longitud, podemos crear nuevas columnas asignándolas por su nombre y confiando en el reciclaje vectorial para llenar la columna según sea necesario. Vamos a crear una nueva columna llamada gc_categories, que inicialmente se llena con valores NA, y luego usar el reemplazo selectivo para asignar valores “low” o “high” dependiendo del contenido de la columna gcs.

    III.6_17_R_124_DF_Newcol_Lowhigh

    Si bien existen enfoques más automatizados para categorizar datos numéricos, el ejemplo anterior ilustra la flexibilidad y potencia del marco de datos y la sintaxis vectorial cubiertos hasta ahora.

    III.6_18_R_125_DF_Newcol_Lowhigh_out

    Una nota final: mientras que la función head () devuelve los primeros elementos de un vector o lista, cuando se aplica a un marco de datos, devuelve un marco de datos similar con solo las primeras filas.

    Matrices y matrices

    Dependiendo del tipo de análisis, es posible que se encuentre trabajando con matrices en R, que son esencialmente vectores bidimensionales. Al igual que los vectores, todos los elementos de una matriz deben ser del mismo tipo, y los intentos de mezclar tipos darán como resultado la autoconversión. Al igual que los marcos de datos, son bidimensionales, y por lo tanto se pueden indexar con la <row_selector><column_selector>sintaxis [,]. También tienen nombres rownames () y colnames ().

    III.6_19_R_125_2_Matrix
    III.6_20_R_125_3_Matrix_out

    Hay una serie de funciones interesantes para trabajar con matrices, incluyendo det () (para calcular el determinante de una matriz) y t () (para transponer una matriz).

    Las matrices generalizan el concepto de datos multidimensionales; donde las matrices solo tienen dos dimensiones, las matrices pueden tener dos, tres o más. La línea a <- array (c (1,1,1,1,2,2,2,2,3,3,3,3), dim = c (2,2,3)), por ejemplo, crea una matriz tridimensional, compuesta por tres matrices de dos por dos. El elemento superior izquierdo se puede extraer como un [1,1,1].

    Ejercicios

    1. Lea el archivo states.txt en un marco de datos, como se describe en el Capítulo 28, Vectores. Extraiga un nuevo marco de datos llamado states_name_pop que contenga solo las columnas para nombre y población.
    2. Usando subset (), extraiga un marco de datos llamado states_gradincome_high que contenga todas las columnas, y todas las filas donde el ingreso sea mayor que la mediana del ingreso o donde hs_grad sea mayor que la mediana de hs_grad. (Hay 35 estados de este tipo enumerados en la tabla.) A continuación, haga la misma extracción con la <row_selector><column_selector>sintaxis [,].
    3. Crear una tabla llamada states_by_region_income, donde las filas se ordenan primero por región y segundo por ingresos. (La función order () puede tomar múltiples parámetros como en orden (vec1, vec2); se consideran a su vez para determinar el orden).
    4. Utilice la <row_selector><column_selector>sintaxis order (), colnames () y [,] para crear un marco de datos states_cols_ordered, donde las columnas están ordenadas alfabéticamente (es decir, hs_grad primero, luego ingreso, luego asesinato, entonces nombre, y así sucesivamente).
    5. La función nrow () devuelve el número de filas en un marco de datos, mientras que rev () invierte un vector y seq (a, b) devuelve un vector de números enteros de a a b (inclusive). Úselos para producir states_by_income_rev, que es el marco de datos de estados pero con filas que aparecen en orden inverso de ingresos (ingresos más altos en la parte superior).
    6. Intente convertir el marco de datos de estados en una matriz ejecutándolo a través de la función.matrix (). ¿Qué pasa con los datos, y por qué crees que es eso?

    1. Desafortunadamente, cuando se imprimen, las comillas se dejan fuera de los nombres de las filas, lo que suele llevar a los programadores a pensar que los índices de fila son lo que se muestra. Del mismo modo, las comillas se dejan fuera de las columnas que son vectores de caracteres (como la columna ids en este ejemplo), lo que puede causar confusión si la columna es un tipo de carácter con elementos como “1", “2", y así sucesivamente, potencialmente llevando al programador a pensar en la columna es numérico. En un giro final de confusión, el uso de la <row_selector><column_selector>sintaxis [,] rompe un patrón común: [] la indexación de un vector siempre devuelve un vector, [] la indexación de una lista siempre devuelve una lista, y [,] <row_selector><column_selector> la indexación de un marco de datos siempre devuelve un marco de datos, a menos que tenga una sola columna, en cuyo caso se devuelve la columna/vector. El remedio para ello es [,, drop = FALSO] <row_selector><column_selector>, que instruye a R a no “soltar” una dimensión.

    This page titled 3.6: Marcos de datos is shared under a CC BY-NC-SA license and was authored, remixed, and/or curated by Shawn T. O’Neil (OSU Press) .