El marco de datos, o conocido en ingles como “data frame”, es una forma en la cual podemos almacenar datos tabulares, similar a una tabla de una hoja de cálculo o una base de datos. Es una forma estructurada de organizar la información en filas y columnas, donde cada columna puede contener diferentes tipos de datos, como numéricos, caracteres, factores, booleanos, etc., y cada fila representa una entrada individual en el conjunto de datos.
Los marcos de datos pueden contener datos de una sola naturaleza (como los vectores o las matrices) o de diversas naturalezas (como las listas o los “data frame”) que nos representa las características de un fenómeno en general.
Heterogeneidad: Cada columna puede contener un tipo de dato diferente, lo que permite tener variables de distintos tipos (por ejemplo, una columna numérica y otra de texto).
Etiquetas: Tanto las filas como las columnas pueden tener nombres, lo que facilita la manipulación y acceso a los datos.
Operaciones sencillas: R tiene muchas funciones
optimizadas para manipular y analizar marcos de datos, como
subset(), merge(), apply(),
dplyr, tidyverse, entre otros.
Los datos en general pueden ser clasificados en de tipo caracter que son aquellos que excluyen los números convencionales, de tipo numérico que son aquellos que comprender a los números reales, y de tipo lógico que comprende las decisiones de FALSO Y TRUE, existen subvariantes de estos que los veremos después.
Como se puede observar, los marcos de datos son la base fundamental para el análisis de datos en R Studios, ya que apartar de estos podemos manipular los datos para la generación de modelos matemáticos, sectorizar cierto tipo de población, la realización de pruebas de hipótesis, y la resolución de conclusiones etc.
Para poder iniciar, primero debemos saber algunas configuraciones básicas de R.
La lectura de datos en R se puede realizar de múltiples formas, la forma mas sencilla, aunque solo nos podría servir para practicar la manipulación de datos, se puede realizar con el comando data(), con el cual podremos cargar una base de datos ya sea del propio R, o de un paquete aledaño.
Para el siguiente caso, necesitaremos el paquete de tidyverse para importar una base de datos con la cual empezaremos a trabajar:
library("tidyverse")
## ── Attaching core tidyverse packages ──────────────────────── tidyverse 2.0.0 ──
## ✔ dplyr 1.1.4 ✔ readr 2.1.5
## ✔ forcats 1.0.0 ✔ stringr 1.5.1
## ✔ ggplot2 3.5.1 ✔ tibble 3.2.1
## ✔ lubridate 1.9.3 ✔ tidyr 1.3.1
## ✔ purrr 1.0.2
## ── Conflicts ────────────────────────────────────────── tidyverse_conflicts() ──
## ✖ dplyr::filter() masks stats::filter()
## ✖ dplyr::lag() masks stats::lag()
## ℹ Use the conflicted package (<http://conflicted.r-lib.org/>) to force all conflicts to become errors
Para realizar nuestra primera lectura de datos, se realiza con el siguiente comando:
data("diamonds")
Así se cargará un conjunto de datos pre-cargados en R, para luego poder utilizarlos de manera efectiva.
Por otro lado, en la mayoría de los casos tendremos que importar nuestras bases de datos desde programas externos. Para lograr esto, el proceso suele ser más complicado; lo más básico es utilizar la función read.table(), que nos ayudará a importar la mayoría de las bases de datos.
Es recomendable crear un proyecto en R para evitar complicaciones al importar bases de datos. También puede funcionar colocar los archivos donde R almacena los datos por defecto. Finalmente, otra opción es copiar directamente la ruta del archivo, aunque esta puede ser un poco más engorrosa, sigue siendo una alternativa viable.
#La importación de datos se realiza de la siguiente manera:
Inmigración <- read.table("C:/Users/Zack_/OneDrive/R-Proyects/Archivos/inmigintnalpry.csv", header = TRUE,
sep = ",",
fileEncoding = "latin1",
nrow = 100)
#Para conocer mas de la función read.table() se realiza con:
help("read.table")
## starting httpd help server ... done
Una forma mas fácil de importar los datos que queremos es mediante la siguiente función:
#datos <- read.table(file.choose())
De esta forma, nos será posible importar nuestras bases de datos. Por otra parte, existen paquetes para tipos de archivos específicos, en los casos donde el separador no es un espacio (” “):
.csv (valores separados por coma): Un archivo CSV es un archivo de texto sin formato que contiene una lista de datos. En su mayoría, utiliza comas para separar (o delimitar) los datos, aunque a veces se usan otros caracteres, como el punto y coma.
.tsv (valores separados por tabuladores): Un archivo .tsv almacena una tabla de datos en la que las columnas están separadas por tabuladores. Por ejemplo, una tabla de datos de una base de datos o los datos de una hoja de cálculo.
.fwf (archivos de ancho fijo): Un archivo .fwf tiene un formato específico que permite guardar datos textuales de forma organizada.
.log: Un archivo .log es generado por la computadora y registra los eventos de los sistemas operativos y otros programas de software.
Las funciones equivalentes en readr suelen ser mucho más rápidas que la función base de R, aunque estas no están en el R base, sino en el paquete tidyverse, y son las siguientes:
#Archivos de valores separados por comas (.csv):
Gasto_G <- read_csv("C:/Users/Zack_/OneDrive/R-Proyects/Clase de R/base_gasto.csv")
## Rows: 213 Columns: 3
## ── Column specification ────────────────────────────────────────────────────────
## Delimiter: ","
## dbl (3): i, gm, im
##
## ℹ Use `spec()` to retrieve the full column specification for this data.
## ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
#Archivos de valores separados por tabulados:
## read_tsv()
#Archivos delimitados en general:
## read_delim()
#Archivos de ancho fijo:
## read_fwf()
#Archivos tabulares en los que las columnas están
#separadas por espacios en blanco:
## read_table():
#Archivos de registro web:
## read_log():
Otra paqueteria que nos ayudara exclusivamente para leer archivos de excel es readxl, con esta paqueteria existe una multitud de ejemplos con los que podemos practicar como el siguiente:
library(readxl)
#Con este comando podemos cargar los ejemplos:
readxl_example()
## [1] "clippy.xls" "clippy.xlsx" "datasets.xls" "datasets.xlsx"
## [5] "deaths.xls" "deaths.xlsx" "geometry.xls" "geometry.xlsx"
## [9] "type-me.xls" "type-me.xlsx"
La función a utilizar para cargar nuestra base de datos es atravez de read_excel(), utilizada para archivos con terminación .xlxs y también para leer un archivo tipo .csv.
Michel_K <- read_excel("C:/Users/Zack_/OneDrive/R-Proyects/Archivos/Modelo_Kaleckiano.xlsx")
head(Michel_K)
Como se puede observar, la función read_excel genera un tibble, en lugar de un data frame:
class(Michel_K)
## [1] "tbl_df" "tbl" "data.frame"
#Para conocer mas información puedes usar el signo de
#"?" y después la función:
?read_excel
Una forma efectiva de agilizar el proceso de carga de nuestra base de datos (y conocer la naturaleza de las variables) en R es la siguiente:
Inmigración <- read.table("C:/Users/Zack_/OneDrive/R-Proyects/Archivos/inmigintnalpry.csv", header = TRUE,
sep =",",
fileEncoding = "latin1",
nrow = 100)
clases <- sapply(Inmigración, class)
clases
## renglon año ent id_ent cvegeo sexo
## "integer" "integer" "character" "integer" "integer" "character"
## edad inmigintnal
## "integer" "numeric"
Inmigración <- read.table("C:/Users/Zack_/OneDrive/R-Proyects/Archivos/inmigintnalpry.csv", header=TRUE,
sep=",",
fileEncoding = "latin1",
colClasses=clases)
Finalmente, la forma de guardar los objetos que invocamos es mediante la función save(). De esta manera, podemos almacenar los objetos que deseemos en un único archivo. Para esto, debemos conocer el directorio del archivo, así como asignarle un nombre al archivo en sí.
Podremos conocer los objetos, variables y/o gráficas que generamos utilizando la función ls(), y eliminarlos con la función rm():
ls()
## [1] "clases" "diamonds" "Gasto_G" "Inmigración" "Michel_K"
#Podremos eliminar aquello que no queremos mediante esta función:
rm(clases)
Conociendo esto, podemos elegir las variables que queremos guardar con la función save():
save(Inmigración, Gasto_G, file="Objetos_Practica.RData")
Finalmente, para cargar los datos que hemos guardado se realiza con esta función:
load("Objetos_Practica.RData")
Igualmente podremos guardar directamente en distintos formatos las bases que hemos modificado, mediante esta función:
write.csv(Gasto_G, file="Gasto_G.csv")
En R existe una gran variedad de objetos con los cuales podemos almacenar, manipular y realizar operaciones con cada una de las bases de datos que tenemos, con el objetivo de su posterior análisis. A continuación, veremos la base de todos los objetos que existen en R.
Los vectores son la estructura base de R, ya que son la primera forma en la cual podemos almacenar nuestros datos. Estos suelen contener datos de una sola naturaleza, aunque a partir de ellos podemos crear otros objetos que contengan variables de distintas características.
La forma primitiva de crear vectores es mediante la función vector(). Estos deben contener solamente datos de una misma naturaleza y se crean de la siguiente forma:
#Vectores numéricos (Valores numéricos):
vector("numeric", length = 10)
## [1] 0 0 0 0 0 0 0 0 0 0
#Vectores tipo carácter (Caracteres entre comillas ""):
vector("character", length = 10)
## [1] "" "" "" "" "" "" "" "" "" ""
#Vectores logicos (Falso y Verdadero)
vector("logical", length = 10)
## [1] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
Existe otra forma de crear vectores, y es utilizando la función c(), colocando los datos directamente dentro del paréntesis. En este caso, la única condición es que los datos sean de la misma naturaleza. Los casos son los siguientes:
#Logical = Si es verdadero o Falso.
I_dont_Know <- c(TRUE, FALSE, TRUE, FALSE, TRUE, FALSE)
print(I_dont_Know)
## [1] TRUE FALSE TRUE FALSE TRUE FALSE
class(I_dont_Know)
## [1] "logical"
Je_ne_sais_pa <- c(T, F, T, F, T, F)
print(Je_ne_sais_pa)
## [1] TRUE FALSE TRUE FALSE TRUE FALSE
class(Je_ne_sais_pa)
## [1] "logical"
#Character = Si es Cualitativo.
Parle_French <- c("Areli","Artemisa","Cinthia","Mayte")
print(Parle_French)
## [1] "Areli" "Artemisa" "Cinthia" "Mayte"
class(Parle_French)
## [1] "character"
#Integer = Si es Cuantitativo y entero.
Real_Enter <- c(1L,2L,3L,4L)
print(Real_Enter)
## [1] 1 2 3 4
class(Real_Enter)
## [1] "integer"
#Real = Si es Cuantitativo y un Numero Real.
Frac_Raz <- c(1.1, 2.2, 3.3, 4.4)
print(Frac_Raz)
## [1] 1.1 2.2 3.3 4.4
class(Frac_Raz)
## [1] "numeric"
#Complex = Si es un numero imaginario.
Img <- c(2+1i, 2+2i, 2+3i)
print(Img)
## [1] 2+1i 2+2i 2+3i
class(Img)
## [1] "complex"
Ya teniendo nuestros vectores, podemos conocer sus propiedades mediante diversas funciones. Estas funciones no solo nos servirán para los vectores, sino también para otros tipos de objetos, con los cuales podremos identificar características básicas del objeto que queremos analizar.
#Saber cual es la naturaleza exacta del vector que queremos conocer:
typeof(Img)
## [1] "complex"
#Saber a cual clase (naturaleza) es a la que pertenece nuestro vector.
class(Parle_French)
## [1] "character"
#Conocer el num de elementos del vector
length(Je_ne_sais_pa)
## [1] 6
A partir de esto, podemos construir variables y sus propiedades básicas, para posteriormente convertirlas de distintas maneras dependiendo nuestras necesidades.
La conversión mas básica es la de agregar nombres a cada uno de los datos que están contenidos en nuestro objeto. Esto se realiza de una forma sencilla, de la siguiente manera:
#Nombrar elementos de vectores:
names(Frac_Raz)= c("Real", "Positivo", "Fraccionario", "Racional")
head(Frac_Raz)
## Real Positivo Fraccionario Racional
## 1.1 2.2 3.3 4.4
Por otra parte, existen vectores con múltiples datos de distintas naturalezas. Esto se puede corregir con la función complex(). Esta función puede convertir los valores de un vector con múltiples elementos a un solo elemento, como en el siguiente caso:
complex <- c(T, 19, 1+3i)
print(complex)
## [1] 1+0i 19+0i 1+3i
Siempre que sea compatible, R puede homogeneizar la naturaleza de los valores que le damos.
La conversión puede suceder de distintas formas. Una de ellas es especificando exactamente qué clase de elemento queremos mediante distintas funciones, las cuales son las siguientes:
#Creación del vector del ejemplo.
element <- vector(mode = "numeric",length =5)
head(element)
## [1] 0 0 0 0 0
#Vector Logico.
as.logical(element)
## [1] FALSE FALSE FALSE FALSE FALSE
#Vector Numerico.
as.numeric(element)
## [1] 0 0 0 0 0
#Vector Caracteristica.
as.character(element)
## [1] "0" "0" "0" "0" "0"
El factor muestra la información con ligeros cambios al del vector común, en estos las comillas no son mostradas y que los niveles son explicitamente impresos.
La forma de convertir vectores a Factores es la siguiente:
factor(element)
## [1] 0 0 0 0 0
## Levels: 0
La búsqueda de elementos nos puede ayudar a localizar un elemento o un cierto rango de elementos de un vector. Esto se puede realizar de distintas formas, la más básica es la siguiente:
head(Parle_French)
## [1] "Areli" "Artemisa" "Cinthia" "Mayte"
Esto se realiza mediante corchetes [], donde fuera del
paréntesis va el nombre de nuestro vector, y dentro del corchete ponemos
el número del dato que queremos invocar y guardar:
Medicina <- Parle_French[3]
head(Medicina)
## [1] "Cinthia"
Esta es la forma en la que podemos invocar un objeto, pero no la única, ya que podemos invocar varios objetos a la vez con una misma función:
mi_vector <- 20:50
mi_vector[1:5]
## [1] 20 21 22 23 24
mi_vector[-9:-15]
## [1] 20 21 22 23 24 25 26 27 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50
Parle_French[c(1, 2, 4)]
## [1] "Areli" "Artemisa" "Mayte"
mi_vector[rep(c(T, F), 10)]
## [1] 20 22 24 26 28 30 32 34 36 38 40 42 44 46 48 50
En este caso, excluye el primer valor, incluye el segundo valor, excluye el tercero, incluye el cuarto, y así sucesivamente.
mi_vector[(mi_vector > 28)]
## [1] 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50
rm(complex, element, Frac_Raz,
I_dont_Know, Je_ne_sais_pa,
Medicina, mi_vector, Parle_French,
Real_Enter, Img)
A partir de los vectores, se pueden crear otros objetos, como los data frames, aunque también existen objetos que pueden contener datos de distinta naturaleza en un solo conjunto.
Una lista es como una caja que puede guardar múltiples objetos diferentes, todos juntos, independientemente de su tipo, tamaño y naturaleza, como números, caracteres, vectores, otros objetos como data frames, e incluso otras listas.
La función básica para crear una lista es list():
list(0, "Hola", TRUE)
## [[1]]
## [1] 0
##
## [[2]]
## [1] "Hola"
##
## [[3]]
## [1] TRUE
Con las siguientes funciones, podemos almacenar, nombrar y ver las características de la lista:
Lista_de_cosas <- list(T, "Crespo", 1L, 7.5, "tontos", 5+4i)
# Ver la naturaleza de cada uno de los datos de la lista:
str(Lista_de_cosas)
## List of 6
## $ : logi TRUE
## $ : chr "Crespo"
## $ : int 1
## $ : num 7.5
## $ : chr "tontos"
## $ : cplx 5+4i
# Nombrar los datos de cada uno de los objetos de la lista:
Num_de_Tontos <- list("Wu" = 2, "Loyd" = 2, "Garmadon" = 3, "Kay" = 4)
View(Num_de_Tontos)
La búsqueda en listas puede ser más compleja que la de vectores, debido a que el proceso se complica al determinar qué se quiere encontrar. Esta es una de las formas de hacerlo:
carro <- list(color = "rojo",
nllantas = 4,
ncilindros = 4,
marca = "Renault")
# Mediante la notación $ es posible la búsqueda de ciertos datos:
carro$color
## [1] "rojo"
# Mediante los [] es posible la búsqueda de objetos dentro de la lista:
carro[c("ncilindros", "nllantas")]
## $ncilindros
## [1] 4
##
## $nllantas
## [1] 4
# A su vez, podremos buscar un dato particular mediante esta función:
carro[["marca"]]
## [1] "Renault"
Será posible hacer búsquedas parciales mediante la opción
exact = FALSE, de la siguiente forma:
carro[["col", exact = FALSE]]
## [1] "rojo"
Si tenemos una lista de listas, será mejor opción buscar con doble corchete para acceder a los datos de manera más rápida:
carro[[c(2, 1)]]
## [1] 4
rm(carro, Num_de_Tontos, Lista_de_cosas)
Una matriz en R es una estructura de datos bidimensional que organiza los datos en filas y columnas, como una tabla. Es similar a un vector, pero con una dimensión extra (filas y columnas). Todas las entradas de una matriz deben ser del mismo tipo de dato y tener la misma naturaleza (para más información, lee el Groosman).
Para crear una matriz, se utiliza la función matrix():
Matriz <- matrix(data = 1:12,
nrow = 4, # Número de filas
ncol = 3) # Número de columnas
print(Matriz)
## [,1] [,2] [,3]
## [1,] 1 5 9
## [2,] 2 6 10
## [3,] 3 7 11
## [4,] 4 8 12
rm(Matriz)
# Más información con esta función:
?matrix()
Igualmente, es posible crear matrices con las funciones cbind() (con la cual especificamos el número de columnas) y rbind() (especificamos el número de filas):
# Se especifica el rango de datos con el que se creará la matriz:
cbind(4:15)
## [,1]
## [1,] 4
## [2,] 5
## [3,] 6
## [4,] 7
## [5,] 8
## [6,] 9
## [7,] 10
## [8,] 11
## [9,] 12
## [10,] 13
## [11,] 14
## [12,] 15
# Generalmente será posible definir los datos que queremos:
rbind(c(4, 10, 24, 36, 1, -4))
## [,1] [,2] [,3] [,4] [,5] [,6]
## [1,] 4 10 24 36 1 -4
# Con esta función es posible crear matrices a partir de un data.frame:
Gasto_Gm <- data.matrix(Gasto_G)
Con esta misma función también es posible elegir las columnas del data frame que queremos usar:
Gasto_Gm <- data.matrix(Gasto_G[-1])
summary(Gasto_Gm)
## gm im
## Min. : 3931 Min. : 1967
## 1st Qu.: 25538 1st Qu.: 25826
## Median : 34233 Median : 47027
## Mean : 45295 Mean : 61520
## 3rd Qu.: 51385 3rd Qu.: 78703
## Max. :374627 Max. :344837
La búsqueda en matrices es una combinación de la búsqueda en vectores y listas. En este caso, deberemos poner las coordenadas exactas para encontrar el dato que buscamos, de la siguiente manera:
Del lado izquierdo se pone la coordenada de la fila y del lado derecho la columna en la que buscaremos:
Gasto_Gm[36, 2]
## im
## 20203.26
# Así, por ejemplo, podremos buscar solamente las filas de esta manera:
Gasto_Gm[45, ]
## gm im
## 11010.97 23184.76
# Y de esta forma seleccionar la columna que queremos:
Gasto_gobierno <- Gasto_Gm[, c("gm"), drop = F]
head(Gasto_gobierno)
## gm
## [1,] 4652.96
## [2,] 35303.82
## [3,] 15423.22
## [4,] 4204.52
## [5,] 5730.85
## [6,] 5695.64
# Combinando las dos, invocamos un dato específico:
Gasto_Gm[45, c("gm")]
## gm
## 11010.97
# También podemos invocar un rango de datos de esta forma:
Gasto_M <- Gasto_Gm[45:67, , drop = F]
nrow(Gasto_M)
## [1] 23
# Estos elementos pueden ser excluidos con esta función:
Gasto_R <- Gasto_Gm[-45:-67, c("im"), drop = F]
nrow(Gasto_Gm)
## [1] 213
nrow(Gasto_R)
## [1] 190
# Así confirmamos que se ha excluido un cierto número de variables.
# También podemos seleccionar ciertos datos específicos de esta forma:
Gasto_Gm[c(65, 66, 70, 94, 133), c("gm", "im")]
## gm im
## [1,] 27734.94 30057.05
## [2,] 28603.25 30326.07
## [3,] 28484.34 31352.44
## [4,] 19627.99 44104.90
## [5,] 62079.15 58466.71
rm(Gasto_gobierno, Gasto_M, Gasto_R)
Finalmente, como podrás observar, se invocan los datos pero en un formato de vector básico. Esto puede cambiar con la función drop, que permite mantener la naturaleza de matriz. Este truco también funciona para los data frames:
# Ejemplo 1:
Gobierno_Gm <- Gasto_Gm[, c("gm"), drop = F]
class(Gobierno_Gm)
## [1] "matrix" "array"
# Ejemplo 2:
Gobierno_Im <- Gasto_Gm[, c("im"), drop = F]
class(Gobierno_Im)
## [1] "matrix" "array"
rm(Gobierno_Gm, Gobierno_Im)
Un data frame en R es una estructura de datos muy utilizada que se asemeja a una tabla o una hoja de cálculo, donde los datos se organizan en filas y columnas. Cada columna en un data frame puede contener datos de distinta naturaleza (números, caracteres, factores, etc.), pero todos los valores dentro de una misma columna deben ser del mismo tipo. Además, el número de datos contenidos en cada columna debe ser igual para que el data frame funcione correctamente.
Para crear data frames, se pueden fusionar vectores con la función data.frame():
# Ejemplo 1
Kaldor <- c(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
Keynes <- c(10, 9, 8, 7, 6, 5, 4, 3, 2, 1)
# Ejemplo 2
Fritura <- c("Takis", "Top_Tops",
"Sabritas_Crujientes",
"Doritos", "Runners")
Puntuaje <- c(2, 4, 1, 5, 3)
# Creación de los Data Frames:
Economistas <- data.frame(Kaldor, Keynes)
Frituras <- data.frame(Fritura, Puntuaje)
# Ver Data Frames:
print(Economistas)
## Kaldor Keynes
## 1 1 10
## 2 2 9
## 3 3 8
## 4 4 7
## 5 5 6
## 6 6 5
## 7 7 4
## 8 8 3
## 9 9 2
## 10 10 1
print(Frituras)
## Fritura Puntuaje
## 1 Takis 2
## 2 Top_Tops 4
## 3 Sabritas_Crujientes 1
## 4 Doritos 5
## 5 Runners 3
rm(Kaldor, Keynes, Frituras, Puntuaje, Economistas)
Asimismo, es posible convertir estructuras de datos de distinta naturaleza en un data frame con as.data.frame():
Gasto <- as.data.frame(Gasto_Gm)
class(Gasto)
## [1] "data.frame"
rm(Gasto, Gasto_Gm)
Es importante mencionar que cuando importamos una base de datos con alguno de los métodos vistos previamente, estos ya se cargan directamente como un data frame, por lo que no será necesario realizar una conversión.
La forma de buscar elementos en un data frame es muy similar a la búsqueda en una matriz, pero con algunas características adicionales provenientes de las listas:
data(cars)
cars$speed
## [1] 4 4 7 7 8 9 10 10 10 11 11 12 12 12 12 13 13 13 13 14 14 14 14 15 15
## [26] 15 16 16 17 17 17 18 18 18 18 19 19 19 20 20 20 20 20 22 23 24 24 24 24 25
cars$speed[cars$dist > 100]
## [1] 24
& (AND) o | (OR),
de la siguiente manera:Mujeres_ID <- Inmigración$edad[Inmigración$ent == "Distrito Federal" &
Inmigración$sexo == "Mujeres"]
mean(Mujeres_ID)
## [1] 54.5
Gasto_01 <- Gasto_G[, setdiff(names(Gasto_G), c("i"))]
En caso de querer borrar más columnas, puedes hacerlo agregando los nombres en el vector de setdiff() como c(“columna1”, “columna2”).
Para calcular el promedio de edad de las mujeres o personas menores de 20 años que han inmigrado alguna vez en su vida, es necesario hacer una búsqueda que sirva como filtro para estudiar dicha población:
GruposV_I <- Inmigración$sexo[Inmigración$edad > 20 |
Inmigración$sexo == "Mujeres"]
Con la variable GruposV_I, es posible saber cuántas personas menores de 20 años o mujeres han inmigrado al país:
table(GruposV_I)
## GruposV_I
## Hombres Mujeres
## 122197 151030
rm(Gasto_01, Mujeres_ID, GruposV_I, cars)
Los tibbles son una versión mejorada de los data frames en R, diseñados para hacer más fácil y eficiente el manejo de datos. Los tibbles provienen del paquete tibble, que es parte del conjunto de herramientas del tidyverse. Si bien los data frames tradicionales son muy útiles, los tibbles introducen ciertas mejoras que los hacen más amigables y menos propensos a errores en algunas situaciones.
Para usarlos, es necesario cargar la paquetería tibble, así como utilizar la función tibble() para crear un tibble:
library("tibble")
tb <- tibble(
Nombre = c("Juan", "Ana", "Luis", "Marta"),
Edad = c(23, 25, 21, 22),
Ciudad = c("Madrid", "Barcelona", "Valencia", "Sevilla"))
print(tb)
## # A tibble: 4 × 3
## Nombre Edad Ciudad
## <chr> <dbl> <chr>
## 1 Juan 23 Madrid
## 2 Ana 25 Barcelona
## 3 Luis 21 Valencia
## 4 Marta 22 Sevilla
# También es posible crear los tibbles de la siguiente manera:
tibble(x = 1:5, y = 1, z = x^2 + y)
rm(tb)
Asimismo, es posible convertir un data frame a un tibble con la función as_tibble():
Inmigración_Tb <- as_tibble(Inmigración)
Entre sus principales características respecto a los data frames tradicionales están:
A diferencia de los data frames tradicionales, los tibbles no imprimen todo el contenido de manera automática cuando los visualizas en la consola. En su lugar, muestran las primeras 10 filas y solo las columnas que caben en la pantalla, lo cual es muy útil cuando trabajas con conjuntos de datos grandes.
Dado que los datos abarcan un gran número de filas, omitiremos el proceso completo:
# Con el data.frame:
glimpse(Inmigración)
## Rows: 302,060
## Columns: 8
## $ renglon <int> 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17,…
## $ año <int> 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990, 1990…
## $ ent <chr> "Aguascalientes", "Aguascalientes", "Aguascalientes", "Agu…
## $ id_ent <int> 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1…
## $ cvegeo <int> 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1…
## $ sexo <chr> "Hombres", "Hombres", "Hombres", "Hombres", "Hombres", "Ho…
## $ edad <int> 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, …
## $ inmigintnal <dbl> 6, 10, 13, 12, 10, 8, 8, 7, 6, 4, 3, 3, 3, 2, 2, 2, 2, 2, …
# Con el tibble:
print(Inmigración_Tb)
## # A tibble: 302,060 × 8
## renglon año ent id_ent cvegeo sexo edad inmigintnal
## <int> <int> <chr> <int> <int> <chr> <int> <dbl>
## 1 1 1990 Aguascalientes 1 1 Hombres 0 6
## 2 2 1990 Aguascalientes 1 1 Hombres 1 10
## 3 3 1990 Aguascalientes 1 1 Hombres 2 13
## 4 4 1990 Aguascalientes 1 1 Hombres 3 12
## 5 5 1990 Aguascalientes 1 1 Hombres 4 10
## 6 6 1990 Aguascalientes 1 1 Hombres 5 8
## 7 7 1990 Aguascalientes 1 1 Hombres 6 8
## 8 8 1990 Aguascalientes 1 1 Hombres 7 7
## 9 9 1990 Aguascalientes 1 1 Hombres 8 6
## 10 10 1990 Aguascalientes 1 1 Hombres 9 4
## # ℹ 302,050 more rows
Cuando seleccionas una sola columna de un tibble, el resultado sigue
siendo un tibble (a diferencia de los data frames, donde a
veces el resultado puede ser un vector si no usas el argumento
drop = FALSE). Esto evita errores relacionados con la
transformación inesperada de datos.
Inm_AyE <- Inmigración_Tb[Inmigración_Tb$año == "2023" &
Inmigración_Tb$ent %in%
c("Distrito Federal", "México"),
c(setdiff(names(Inmigración_Tb),
c("renglon", "id_ent", "cvegeo")))]
# Verificación:
class(Inm_AyE)
## [1] "tbl_df" "tbl" "data.frame"
Otras características de los tibbles incluyen:
character por
defecto.Conociendo esto, podrás considerar cuál de los dos marcos de datos te conviene usar. Cada uno tiene sus ventajas, pero lo interesante de los tibbles es su manipulación interna. Por ello, veremos brevemente cómo manipular marcos de datos.
La edición de un marco de datos (data frame) en R se refiere a la manipulación, modificación o transformación de su estructura y contenido para adaptarlo a las necesidades del análisis. Esto incluye operaciones como:
Estas operaciones son fundamentales para preparar los datos antes de realizar análisis estadísticos, modelado o visualización. Para lograr dicho propósito se usa la paquetería dplyr, que viene incluida en el tidyverse. Simplemente cargando esta paquetería bastará para empezar:
library("dplyr")
library("magrittr")
library("here")
library("skimr")
library("janitor")
Las pipes (o tubos) (%>%) en R son
una herramienta del paquete magrittr que nos permiten
filtrar datos de un marco de datos de manera secuencial, encadenando
funciones. Esto hace que el código sea más legible y fácil de escribir,
especialmente cuando realizas varias operaciones consecutivas sobre un
conjunto de datos.
Para invocar un tubo se utiliza la combinación Ctrl + Shift + M. Su funcionamiento permite pasar el resultado de una función directamente como argumento a la siguiente función, sin necesidad de crear variables intermedias o anidar llamadas de funciones.
Para obtener las estadísticas básicas de la edad de las mujeres menores de 20 años que inmigraron de la Ciudad de México entre 1994 y el año 2000, en R Base generalmente sería de la siguiente manera:
# Primero generamos la tabla base para los estadísticos:
InmigraciónF_CDMX <- Inmigración[Inmigración$año >= 1994 &
Inmigración$año <= 2000 &
Inmigración$sexo == "Mujeres" &
Inmigración$edad < 20 &
Inmigración$ent == "Distrito Federal",
c(setdiff(names(Inmigración),
c("renglon", "id_ent", "cvegeo",
"inmigintnal")))]
# Después generamos los estadísticos deseados:
Est_Descriptiva_F_01 <- c(Num_Mujeres = sum(InmigraciónF_CDMX$sexo ==
"Mujeres"),
Media_Edad = mean(InmigraciónF_CDMX$edad),
Mediana_Edad = median(InmigraciónF_CDMX$edad),
Desv_Est_Edad = sd(InmigraciónF_CDMX$edad))
# Finalmente, visualizamos los estadísticos:
print(Est_Descriptiva_F_01)
## Num_Mujeres Media_Edad Mediana_Edad Desv_Est_Edad
## 140.000000 9.500000 9.500000 5.786986
Como se puede observar, el proceso es complejo y anidado, lo que lo hace difícil de entender completamente. Por eso, el uso de pipes mejora este tipo de filtro.
En R Magrittr podemos obtener los estadísticos directamente sin necesidad de generar una tabla previa, conservando el formato original mediante los tibbles:
Est_Descriptiva_F_02 <- Inmigración_Tb %>%
select(año, ent, sexo, edad) %>%
filter(año >= 1994 & año <= 2000,
sexo == "Mujeres",
ent == "Distrito Federal",
edad < 20) %>%
summarise(Num_Mujeres = sum(sexo == "Mujeres"),
Media_Edad = mean(edad),
Mediana_Edad = median(edad),
Desv_Est_Edad = sd(edad))
# Posteriormente, simplemente revisamos los resultados:
print(Est_Descriptiva_F_02)
## # A tibble: 1 × 4
## Num_Mujeres Media_Edad Mediana_Edad Desv_Est_Edad
## <int> <dbl> <dbl> <dbl>
## 1 140 9.5 9.5 5.79
rm(InmigraciónF_CDMX, Est_Descriptiva_F_01, Est_Descriptiva_F_02)
Como puedes ver, las pipes simplifican considerablemente la tarea de filtrar una base de datos. Esto no solo nos ayuda a ser más rápidos en la tarea, sino que también permite que nuestro código sea más organizado. Por lo tanto, es importante saber utilizarlas para optimizar nuestro trabajo.
La primera forma de saber qué tipo de datos tenemos es a través de un resumen general de nuestro marco de datos. Esto se puede hacer con las siguientes funciones:
# Para este caso, usaremos los datos de esta paquetería:
library("palmerpenguins")
head(penguins)
str(penguins)
## tibble [344 × 8] (S3: tbl_df/tbl/data.frame)
## $ species : Factor w/ 3 levels "Adelie","Chinstrap",..: 1 1 1 1 1 1 1 1 1 1 ...
## $ island : Factor w/ 3 levels "Biscoe","Dream",..: 3 3 3 3 3 3 3 3 3 3 ...
## $ bill_length_mm : num [1:344] 39.1 39.5 40.3 NA 36.7 39.3 38.9 39.2 34.1 42 ...
## $ bill_depth_mm : num [1:344] 18.7 17.4 18 NA 19.3 20.6 17.8 19.6 18.1 20.2 ...
## $ flipper_length_mm: int [1:344] 181 186 195 NA 193 190 181 195 193 190 ...
## $ body_mass_g : int [1:344] 3750 3800 3250 NA 3450 3650 3625 4675 3475 4250 ...
## $ sex : Factor w/ 2 levels "female","male": 2 1 1 NA 1 2 1 2 NA NA ...
## $ year : int [1:344] 2007 2007 2007 2007 2007 2007 2007 2007 2007 2007 ...
Es una manera compacta de ver la estructura del data frame y los primeros valores de cada columna.
summary(penguins)
## species island bill_length_mm bill_depth_mm
## Adelie :152 Biscoe :168 Min. :32.10 Min. :13.10
## Chinstrap: 68 Dream :124 1st Qu.:39.23 1st Qu.:15.60
## Gentoo :124 Torgersen: 52 Median :44.45 Median :17.30
## Mean :43.92 Mean :17.15
## 3rd Qu.:48.50 3rd Qu.:18.70
## Max. :59.60 Max. :21.50
## NA's :2 NA's :2
## flipper_length_mm body_mass_g sex year
## Min. :172.0 Min. :2700 female:165 Min. :2007
## 1st Qu.:190.0 1st Qu.:3550 male :168 1st Qu.:2007
## Median :197.0 Median :4050 NA's : 11 Median :2008
## Mean :200.9 Mean :4202 Mean :2008
## 3rd Qu.:213.0 3rd Qu.:4750 3rd Qu.:2009
## Max. :231.0 Max. :6300 Max. :2009
## NA's :2 NA's :2
Este resumen proporciona una visión rápida de los valores clave en cada variable y es especialmente útil para ver estadísticas básicas como la mediana, la media y la cantidad de datos faltantes (NA).
glimpse(penguins)
## Rows: 344
## Columns: 8
## $ species <fct> Adelie, Adelie, Adelie, Adelie, Adelie, Adelie, Adel…
## $ island <fct> Torgersen, Torgersen, Torgersen, Torgersen, Torgerse…
## $ bill_length_mm <dbl> 39.1, 39.5, 40.3, NA, 36.7, 39.3, 38.9, 39.2, 34.1, …
## $ bill_depth_mm <dbl> 18.7, 17.4, 18.0, NA, 19.3, 20.6, 17.8, 19.6, 18.1, …
## $ flipper_length_mm <int> 181, 186, 195, NA, 193, 190, 181, 195, 193, 190, 186…
## $ body_mass_g <int> 3750, 3800, 3250, NA, 3450, 3650, 3625, 4675, 3475, …
## $ sex <fct> male, female, female, NA, female, male, female, male…
## $ year <int> 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007…
Es una manera más compacta de ver la estructura del data frame y los primeros valores de cada columna.
skim_without_charts(penguins)
| Name | penguins |
| Number of rows | 344 |
| Number of columns | 8 |
| _______________________ | |
| Column type frequency: | |
| factor | 3 |
| numeric | 5 |
| ________________________ | |
| Group variables | None |
Variable type: factor
| skim_variable | n_missing | complete_rate | ordered | n_unique | top_counts |
|---|---|---|---|---|---|
| species | 0 | 1.00 | FALSE | 3 | Ade: 152, Gen: 124, Chi: 68 |
| island | 0 | 1.00 | FALSE | 3 | Bis: 168, Dre: 124, Tor: 52 |
| sex | 11 | 0.97 | FALSE | 2 | mal: 168, fem: 165 |
Variable type: numeric
| skim_variable | n_missing | complete_rate | mean | sd | p0 | p25 | p50 | p75 | p100 |
|---|---|---|---|---|---|---|---|---|---|
| bill_length_mm | 2 | 0.99 | 43.92 | 5.46 | 32.1 | 39.23 | 44.45 | 48.5 | 59.6 |
| bill_depth_mm | 2 | 0.99 | 17.15 | 1.97 | 13.1 | 15.60 | 17.30 | 18.7 | 21.5 |
| flipper_length_mm | 2 | 0.99 | 200.92 | 14.06 | 172.0 | 190.00 | 197.00 | 213.0 | 231.0 |
| body_mass_g | 2 | 0.99 | 4201.75 | 801.95 | 2700.0 | 3550.00 | 4050.00 | 4750.0 | 6300.0 |
| year | 0 | 1.00 | 2008.03 | 0.82 | 2007.0 | 2007.00 | 2008.00 | 2009.0 | 2009.0 |
Este resumen es más detallado que summary() e incluye información sobre valores faltantes (NA) y estadísticas descriptivas detalladas de cada variable.
summary(select(penguins, species, sex, year))
## species sex year
## Adelie :152 female:165 Min. :2007
## Chinstrap: 68 male :168 1st Qu.:2007
## Gentoo :124 NA's : 11 Median :2008
## Mean :2008
## 3rd Qu.:2009
## Max. :2009
skim_without_charts(select(penguins, -species, -sex, -year))
| Name | select(penguins, -species… |
| Number of rows | 344 |
| Number of columns | 5 |
| _______________________ | |
| Column type frequency: | |
| factor | 1 |
| numeric | 4 |
| ________________________ | |
| Group variables | None |
Variable type: factor
| skim_variable | n_missing | complete_rate | ordered | n_unique | top_counts |
|---|---|---|---|---|---|
| island | 0 | 1 | FALSE | 3 | Bis: 168, Dre: 124, Tor: 52 |
Variable type: numeric
| skim_variable | n_missing | complete_rate | mean | sd | p0 | p25 | p50 | p75 | p100 |
|---|---|---|---|---|---|---|---|---|---|
| bill_length_mm | 2 | 0.99 | 43.92 | 5.46 | 32.1 | 39.23 | 44.45 | 48.5 | 59.6 |
| bill_depth_mm | 2 | 0.99 | 17.15 | 1.97 | 13.1 | 15.60 | 17.30 | 18.7 | 21.5 |
| flipper_length_mm | 2 | 0.99 | 200.92 | 14.06 | 172.0 | 190.00 | 197.00 | 213.0 | 231.0 |
| body_mass_g | 2 | 0.99 | 4201.75 | 801.95 | 2700.0 | 3550.00 | 4050.00 | 4750.0 | 6300.0 |
Con estas funciones, podemos empezar la inspección de nuestros datos y limpiarlos para, por ejemplo, cambiar el nombre de un cierto número de variables.
Para poder cambiar el nombre de las columnas de nuestro marco de datos, primero debemos saber cuáles son esos nombres, los cuales se pueden visualizar con colnames():
colnames(penguins)
## [1] "species" "island" "bill_length_mm"
## [4] "bill_depth_mm" "flipper_length_mm" "body_mass_g"
## [7] "sex" "year"
hotel_data <- read_csv("C:/Users/Zack_/OneDrive/R-Proyects/Archivos/hotel_bookings.csv", col_names = TRUE)
Sabiendo los nombres, podremos usar la función rename() para iniciar la transformación:
rename(penguins, sexo = sex)
rename_with(penguins, toupper) # Cambia los títulos a mayúsculas.
rename_with(penguins, tolower) # Cambia los títulos a minúsculas.
Gracias a los “tubos” (pipes), podemos cambiar el nombre de tres columnas del objeto hotel_data, guardarlas en un tibble único y luego generar un resumen general del mismo:
colnames(hotel_data)
## [1] "hotel" "is_canceled"
## [3] "lead_time" "arrival_date_year"
## [5] "arrival_date_month" "arrival_date_week_number"
## [7] "arrival_date_day_of_month" "stays_in_weekend_nights"
## [9] "stays_in_week_nights" "adults"
## [11] "children" "babies"
## [13] "meal" "country"
## [15] "market_segment" "distribution_channel"
## [17] "is_repeated_guest" "previous_cancellations"
## [19] "previous_bookings_not_canceled" "reserved_room_type"
## [21] "assigned_room_type" "booking_changes"
## [23] "deposit_type" "agent"
## [25] "company" "days_in_waiting_list"
## [27] "customer_type" "adr"
## [29] "required_car_parking_spaces" "total_of_special_requests"
## [31] "reservation_status" "reservation_status_date"
trimmed_df <- hotel_data %>%
select(hotel, is_canceled, lead_time) %>%
rename(Hotel = hotel,
Cancelados = is_canceled,
Tiempo = lead_time)
summary(trimmed_df)
## Hotel Cancelados Tiempo
## Length:119390 Min. :0.0000 Min. : 0
## Class :character 1st Qu.:0.0000 1st Qu.: 18
## Mode :character Median :0.0000 Median : 69
## Mean :0.3704 Mean :104
## 3rd Qu.:1.0000 3rd Qu.:160
## Max. :1.0000 Max. :737
Realizaremos algo similar con la función Michel_K, cambiando el nombre de las variables de nuestro interés. Posteriormente, aplicaremos el logaritmo natural a todas las variables para, finalmente, generar un resumen de los datos:
colnames(Michel_K)
## [1] "Trimestre" "INPC = 2018" "PIB" "P = EBO" "I = FBC"
## [6] "CG" "Im" "DF" "X" "M"
## [11] "BC" "AB" "IK" "s" "A"
Ganancias <- Michel_K %>%
rename(G = "P = EBO",
I = "I = FBC",
T = Im) %>%
select(-c("INPC = 2018", AB, Trimestre, DF, BC)) %>%
log() %>%
skim_without_charts()
View(Ganancias)
rm(Ganancias, trimmed_df)
El filtrado de datos es fundamental para poder empezar a transformar nuestros datos y continuar con un análisis más detallado de estos. Esto se puede hacer de diversas formas, pero siempre teniendo en cuenta los pipes como un factor clave para que este proceso sea lo más sencillo posible.
Un primer ejemplo es mediante la función arrange(), que simplemente ordena los datos de mayor a menor, como en el siguiente caso:
# En este caso, poniendo el símbolo - se invierte el orden.
año <- arrange(penguins, -year)
La función filter(), vista con anterioridad, nos permite seleccionar un cierto tipo de datos con características específicas, como en el siguiente caso:
islands <- penguins %>% filter(island == "Torgersen") %>%
filter(bill_length_mm <= 58.0)
head(islands)
También es posible simplificar el filtro, como se realizó en la búsqueda de elementos del data frame:
islands <- penguins %>% filter(island == "Torgersen" &
bill_length_mm <= 58.0)
head(islands)
rm(islands, año)
Otra función muy útil es group_by(), que a diferencia de select, agrupa las filas según una o más columnas para hacer cálculos. Esta función se enfoca en filas y grupos, permitiendo un filtrado más específico que el anterior:
Sexo <- penguins %>%
group_by(sex) %>%
drop_na() %>%
summarise(Sex_Mean_Length = mean(bill_length_mm),
Sex_Max_Length = max(bill_length_mm))
print(Sexo)
## # A tibble: 2 × 3
## sex Sex_Mean_Length Sex_Max_Length
## <fct> <dbl> <dbl>
## 1 female 42.1 58
## 2 male 45.9 59.6
Generalmente, group_by() se usa para crear resúmenes estadísticos a nuestro modo, algo que sería más complicado con la función select():
sex_estadistic <- penguins %>%
group_by(species, island, sex) %>%
drop_na() %>%
summarize(Mean_Flipper = mean(flipper_length_mm),
Desv_Flipper = sd(flipper_length_mm),
.groups = "drop") %>%
arrange(species)
#Media y Desviación Estandar de las aletas:
print(sex_estadistic)
## # A tibble: 10 × 5
## species island sex Mean_Flipper Desv_Flipper
## <fct> <fct> <fct> <dbl> <dbl>
## 1 Adelie Biscoe female 187. 6.74
## 2 Adelie Biscoe male 190. 6.46
## 3 Adelie Dream female 188. 5.51
## 4 Adelie Dream male 192. 6.80
## 5 Adelie Torgersen female 188. 4.64
## 6 Adelie Torgersen male 195. 5.92
## 7 Chinstrap Dream female 192. 5.75
## 8 Chinstrap Dream male 200. 5.98
## 9 Gentoo Biscoe female 213. 3.90
## 10 Gentoo Biscoe male 222. 5.67
rm(Sexo, sex_estadistic)
Ya con nuestro marco de datos creado, será posible realizar la combinación, fusión y separación de nuevas columnas, utilizando diversas funciones que veremos a continuación.
Mediante la función mutate(), podremos agregar una nueva columna combinando dos o más columnas o simplemente aplicando un operador a estas, con el objetivo de generar una nueva variable que sea de interés.
Crearemos un tibble llamado Noches_Promedio, que nos indique el porcentaje de las noches respecto a las noches promedio que generalmente suelen tomar los huéspedes por mes. Para crear este estadístico, necesitaremos la función mutate(), así como otras funciones vistas previamente para generar una nueva columna.
# Generación del Tibble:
Noches_Promedio <- hotel_data %>%
rename(Mes = arrival_date_month) %>%
filter(is_canceled == 1) %>%
mutate(Noches = stays_in_week_nights / mean(stays_in_week_nights)) %>%
select(Noches, Mes)
View(Noches_Promedio)
Como podemos observar, las noches que superan el valor de 1 son aquellas que sobrepasan el promedio de noches que los huéspedes suelen permanecer en el hotel. Ahora podremos ver cuáles son los meses que logran superar dicha característica.
# Generación de la gráfica:
ggplot(Noches_Promedio, aes(x = Mes, y = Noches)) +
geom_bar(stat = "summary",
fun = "mean",
fill = "goldenrod",
color = "black",
width = 0.8) +
geom_hline(yintercept = 1,
color = "black",
linetype = "dashed",
size = 1) +
labs(title = "Noches en el hotel por mes",
subtitle = "En términos porcentuales",
x = "Meses del año",
y = "Noches reservadas") +
theme_minimal() +
theme(
plot.title = element_text(hjust = 0.5,
size = 20,
face = "bold"),
plot.subtitle = element_text(hjust = 0.5,
size = 12,
face = "italic",
color = "#2F2F2F"),
axis.title.x = element_text(size = 13),
axis.title.y = element_text(size = 13),
panel.grid.major = element_line(color = "#2F2F2F",
size = 0.5),
panel.background = element_rect(fill = "#D3D3D3"),
plot.background = element_rect(fill = "pink"))
Como se puede observar, solamente los meses de marzo, junio, julio y agosto superan el valor de 1, lo cual nos indica que en esos meses en particular, la duración de estancias por noche en el hotel suele ser mayor al promedio general.
Otro ejemplo que realizaremos es la generación de una gráfica de densidad acerca de los residuos de la regresión de las ganancias respecto a otros estadísticos, con el fin de analizar si nuestros residuos presentan un comportamiento acorde a la media y tienden a tener una distribución normal:
# Creación del autorregresivo:
G_Logaritmo <- tibble(G = log(Michel_K$`P = EBO`))
Arima <- ar(G_Logaritmo, order.max = 1)
Arima_1 <- tibble(Residuos = as.numeric(Arima$resid))
head(Arima_1)
rm(G_Logaritmo, Arima)
# Creación del tibble:
Modelo_Kaleckiano <- Michel_K %>%
rename(Ganancias_G = 'P = EBO',
Inversion_I = 'I = FBC',
Consumo_Gobierno_CG = 'CG',
Impuestos_T = 'Im',
Defic_Fiscal_DF = 'DF',
Exportaciones_X = 'X',
Importaciones_M = 'M',
Balanza_Comercial_BC = 'BC',
Ingreso_Capitalistas_Ik = 'IK',
Ahorro_s = 's') %>%
mutate(Conjunto_A = Inversion_I +
Defic_Fiscal_DF +
Balanza_Comercial_BC,
Constante_A = lag(Conjunto_A, 1),
Ahorro_st = lag(Ahorro_s, 1)) %>%
select(Ganancias_G,
Ahorro_st,
Constante_A,
Inversion_I) %>%
log() %>%
mutate(Autoregresivo_G = Arima_1$Residuos)
rm(Arima_1, Michel_K)
head(Modelo_Kaleckiano)
# Creación de la Regresión lineal:
Regresión_G <- lm(Ganancias_G ~ Inversion_I + Constante_A + Ahorro_st + Autoregresivo_G, data = Modelo_Kaleckiano)
summary(Regresión_G)
##
## Call:
## lm(formula = Ganancias_G ~ Inversion_I + Constante_A + Ahorro_st +
## Autoregresivo_G, data = Modelo_Kaleckiano)
##
## Residuals:
## Min 1Q Median 3Q Max
## -0.060304 -0.020430 -0.002984 0.020759 0.073826
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) 8.87307 0.72200 12.290 < 2e-16 ***
## Inversion_I 0.22646 0.04934 4.589 2.55e-05 ***
## Constante_A 0.12665 0.02641 4.796 1.24e-05 ***
## Ahorro_st 0.12674 0.01539 8.234 3.19e-11 ***
## Autoregresivo_G 0.69859 0.09760 7.158 1.90e-09 ***
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 0.02884 on 56 degrees of freedom
## (1 observation deleted due to missingness)
## Multiple R-squared: 0.8476, Adjusted R-squared: 0.8367
## F-statistic: 77.85 on 4 and 56 DF, p-value: < 2.2e-16
Density_G <- density(Regresión_G$residuals)
par(bg = "pink")
plot(Density_G,
main = "Densidad del Modelo Kaleckiano",
cex.main = 2,
font.main = 2,
ylab = "Densidad",
col = "black",
lwd = 1,
type = "l")
mtext("Prueba de normalidad",
side = 3,
line = 0.3,
cex = 1.0)
polygon(Density_G,
col = "black",
border = "black")
Como se observa en la gráfica, los residuos parecen comportarse de manera normal. Sin embargo, es necesario realizar una prueba de normalidad convencional para confirmarlo.
rm(Density_G, Modelo_Kaleckiano, Regresión_G)
Finalmente, será posible unir distintas columnas mediante la función unite(), para fusionarlas y crear una sola, como se muestra a continuación:
example_unite <- hotel_data %>%
select(arrival_date_year,
arrival_date_month) %>%
unite(Mes_y_Año,
c("arrival_date_month", "arrival_date_year"),
sep = " ")
head(example_unite)
Con la función separate(), podemos separar las columnas de manera sencilla:
example_separate <- example_unite %>%
separate(Mes_y_Año,
into = c("Mes", "Año"),
sep = " ")
head(example_separate)
De esta forma, podemos modificar gran parte de nuestros marcos de datos a nuestro antojo. Estas funciones son muy útiles. A continuación, veremos algunas funciones más avanzadas en R, que llevarán este proceso al siguiente nivel:
Próximamente…
rm(example_unite, example_separate)