Análisis Exploratorio & Preprocesamiento -Volumen 1-
Santiago Banchero
Leo Lucianna
Juan Manuel Fernandez
Minería de Datos - UBA
R es un lenguaje de programación con un enfoque al análisis estadístico.
R es software libre y es uno de los lenguajes mas utilizados en investigación por la comunidad estadística y minería de datos.
Se distribuye bajo la licencia GNU GPL. Está disponible para los sistemas operativos Unix y GNU/Linux, Windows & Macintosh.
[1] https://www.r-project.org/
[2] https://www.rstudio.com/
Un dataset consiste en una representación de un conjunto de hechos/individuos a través de un conjunto de características.
Para describir un dataset se analizan esas características (variables) y sus relaciones.
Las variables, a grandes rasgos pueden ser:
Es importante conocer los tipos de datos, dado que ello nos permite decidir que tipo de análisis utilizar.
El análisis de datos exploratorio (EDA) tiene por objetivo identificar las principales características de un conjunto de datos mediante un número reducido de gráficos y/o valores.
Consiste en:
Iris: 150 instancias de flores de la planta iris en sus variedades:
Las caracteristicas son:
data(iris)
names(iris)
[1] "Sepal.Length" "Sepal.Width" "Petal.Length" "Petal.Width"
[5] "Species"
pie(table(iris$Species))
Podemos cargar el dataset de, al menos, dos maneras:
library(readr)
getwd()
[1] "C:/Users/unlu/Google Drive/PC-Juan/Docencia & Investigacion/Docencia/Mineria de Datos-UBA/LAB01/2019 vFinal/Presentacion-R"
#iris <- read_csv("C:/Users/Usuario/Google Drive/PC-Juan/Docencia & Investigacion/Docencia/Mineria de Datos-UBA/iris.csv")
Los datasets serán contenidos en un dato de tipo Data.Frame…
El dataframe es una estructura de datos similar a la matriz, a diferencia que puede tener columnas con diferentes tipos de datos:
str(iris)
'data.frame': 150 obs. of 5 variables:
$ Sepal.Length: num 5.1 4.9 4.7 4.6 5 5.4 4.6 5 4.4 4.9 ...
$ Sepal.Width : num 3.5 3 3.2 3.1 3.6 3.9 3.4 3.4 2.9 3.1 ...
$ Petal.Length: num 1.4 1.4 1.3 1.5 1.4 1.7 1.4 1.5 1.4 1.5 ...
$ Petal.Width : num 0.2 0.2 0.2 0.2 0.2 0.4 0.3 0.2 0.2 0.1 ...
$ Species : Factor w/ 3 levels "setosa","versicolor",..: 1 1 1 1 1 1 1 1 1 1 ...
Es la estructura de datos mas utilizada por su versatilidad y potencia. Podemos cargar datasets a partir de distintos tipos de archivos o podemos crearlas a partir de la conjunción de listas/arrays con la función data.frame().
Accedemos por Atributo/Columna:
iris$Sepal.Length[1:5]
[1] 5.1 4.9 4.7 4.6 5.0
iris[1:5,1]
[1] 5.1 4.9 4.7 4.6 5.0
Accedemos por Instancia/Fila:
iris[3,1:3]
Sepal.Length Sepal.Width Petal.Length
3 4.7 3.2 1.3
iris[2,-c(4,5)]
Sepal.Length Sepal.Width Petal.Length
2 4.9 3 1.4
Seleccionamos Instancias que cumplen una condición:
iris[iris$Species=="setosa" & iris$Sepal.Length>5.2,3:4]
Petal.Length Petal.Width
6 1.7 0.4
11 1.5 0.2
15 1.2 0.2
16 1.5 0.4
17 1.3 0.4
19 1.7 0.3
21 1.7 0.2
32 1.5 0.4
34 1.4 0.2
37 1.3 0.2
49 1.5 0.2
Podemos AGREGAR una instancia o un conjunto de instancias:
nuevas.filas<-data.frame(Sepal.Length=5, Sepal.Width=5, Petal.Length=5, Petal.Width=5, Species="Data Mining")
iris<-rbind(iris, nuevas.filas)
Podemos MODIFICAR una instancia o un conjunto de instancias:
iris[1,1:4]=c(4.4,4.4,4.4,4.4)
iris[iris$Species=="setosa",1:4]=iris[iris$Species=="setosa",1:4]*5
Podemos ELIMINAR una instancia o un conjunto de instancias:
iris<-iris[-c(1:5),]
Deciamos que para describir un dataset se analizan sus variables y las relaciones entre ellas.
Nos interesa la distribución de la variable, que está determinada por los valores que toma esa variable y la frecuencia con la que los toma.
A tener en cuenta:
str(iris)
'data.frame': 150 obs. of 5 variables:
$ Sepal.Length: num 5.1 4.9 4.7 4.6 5 5.4 4.6 5 4.4 4.9 ...
$ Sepal.Width : num 3.5 3 3.2 3.1 3.6 3.9 3.4 3.4 2.9 3.1 ...
$ Petal.Length: num 1.4 1.4 1.3 1.5 1.4 1.7 1.4 1.5 1.4 1.5 ...
$ Petal.Width : num 0.2 0.2 0.2 0.2 0.2 0.4 0.3 0.2 0.2 0.1 ...
$ Species : Factor w/ 3 levels "setosa","versicolor",..: 1 1 1 1 1 1 1 1 1 1 ...
Vemos el objeto y sus instancias:
View(iris) # Instancias del dataset
Mas datos:
summary(iris)
Sepal.Length Sepal.Width Petal.Length Petal.Width
Min. :4.300 Min. :2.000 Min. :1.000 Min. :0.100
1st Qu.:5.100 1st Qu.:2.800 1st Qu.:1.600 1st Qu.:0.300
Median :5.800 Median :3.000 Median :4.350 Median :1.300
Mean :5.843 Mean :3.057 Mean :3.758 Mean :1.199
3rd Qu.:6.400 3rd Qu.:3.300 3rd Qu.:5.100 3rd Qu.:1.800
Max. :7.900 Max. :4.400 Max. :6.900 Max. :2.500
Species
setosa :50
versicolor:50
virginica :50
Decimos que nos interesa la distribución de la variable, que está determinada por los valores que toma esa variable y la frecuencia con la que los toma. Las herramientas son:
También nos interesa la relación entre las variables:
Entre las medidas de posición mas conocidas se encuentran:
Media aritmética:
mean(iris$Sepal.Length)
[1] 5.843333
Media truncada: (Elimina outliers)
mean(iris$Sepal.Length, 0.05)
[1] 5.820588
Mediana y Moda:
median(iris$Sepal.Length)
[1] 5.8
library(modeest) #Cargar la libreria
mfv(iris$Sepal.Length) #Calcular la moda de un atributo
[1] 5
Aplicando las medidas por especie:
aggregate(Petal.Length ~ Species, data=iris, FUN=median)
Species Petal.Length
1 setosa 1.50
2 versicolor 4.35
3 virginica 5.55
Para variables discretas:
pie(table(iris$Species))
barplot(table(iris$Species))
Para variables continuas: Histogramas
hist(iris$Sepal.Length)
Estas medidas nos dicen que tan distintas o similares tienden a ser las observaciones respecto a un valor particular (medida de tendencia central).
Rango:
max(iris$Sepal.Length)-min(iris$Sepal.Length)
[1] 3.6
range(iris$Sepal.Length)
[1] 4.3 7.9
Varianza (sumatoria de las diferencias cuadraticas con respecto a la media) y Desvio estandar (raiz cuadrada):
var(iris$Sepal.Length)
[1] 0.6856935
sd(iris$Sepal.Length)
[1] 0.8280661
Percentiles
El percentil k es un valor tal que el p% de las observaciones se encuentran debajo de este y el (100-k))% por encima del mismo.
Cuantil Caso particular del concepto anterior donde:
quantile(iris$Sepal.Length,seq(0,1,0.01))
quantile(iris$Sepal.Length,seq(0,1,0.25))
0% 25% 50% 75% 100%
4.3 5.1 5.8 6.4 7.9
Diagramas de Cajas: Brindan informacion sobre
boxplot(iris$Sepal.Length ~ iris$Species)
plot(iris$Petal.Length, iris$Petal.Width,col=iris$Species)
pairs(iris[,1:4],col=iris$Species)
Estas medidas son utilizadas para verificar como varía una variable con respecto a otra.
Podemos calcular la covarianza (dependiente de la escala de las variables)
cov(iris$Petal.Length,iris$Petal.Width)
[1] 1.295609
O el coeficiente de correlación de Pearson (normalizado)
cor(iris$Petal.Length,iris$Petal.Width)
[1] 0.9628654
Para estudiar las relaciones entre variables, podemos utilizar:
Scatter 3D:
library(scatterplot3d)
scatterplot3d(iris$Sepal.Length, iris$Sepal.Width, iris$Petal.Length)
Gráfico de coordenadas paralelas:
library(MASS)
parcoord(iris[1:4], col=iris$Species,var.label=T)
En esta clase, vamos a abordar las siguientes técnicas a través del lenguaje R:
Existen, varias operaciones para integrar datos, por ejemplo merge:
productos<-data.frame(Codigo=c(45, 46), Denominacion=c("Licuadora", "TV 4k"), Precio=c(1245.10, 14742))
head(productos)
Codigo Denominacion Precio
1 45 Licuadora 1245.1
2 46 TV 4k 14742.0
stock<-data.frame(Cod=c(45, 46), stock=c(8650, 145))
dataset<-merge(productos, stock, by.x = "Codigo", by.y = "Cod")
head(dataset)
Codigo Denominacion Precio stock
1 45 Licuadora 1245.1 8650
2 46 TV 4k 14742.0 145
Bonus Track: Librerías sqldf y dplyr.
Con sqldf vamos a manipular los dataframes como si fueran tablas sql:
library(sqldf)
join_string = "SELECT Codigo, Denominacion, Precio, stock as Stock FROM productos p INNER JOIN stock s ON p.Codigo=s.Cod"
sql_query = sqldf(join_string,stringsAsFactors = FALSE)
head(sql_query)
Codigo Denominacion Precio Stock
1 45 Licuadora 1245.1 8650
2 46 TV 4k 14742.0 145
Otra librería muy conocida de R para la manipulación de dataframes es dplyr:
library(dplyr)
data.dplyr = inner_join(productos, stock, by = c("Codigo" = "Cod"))
head(data.dplyr)
Codigo Denominacion Precio stock
1 45 Licuadora 1245.1 8650
2 46 TV 4k 14742.0 145
Además, como vimos antes, debemos tener en cuenta:
names(stock)
[1] "Cod" "stock"
names(stock)[1]="Codigo"
names(stock)
[1] "Codigo" "stock"
celsius=c(26,32)
fahrenheit=(celsius*1.8)+32
print(fahrenheit)
[1] 78.8 89.6
library(lubridate)
fechas <- c(as.Date("2011-06-26"), as.Date("2013-07-15"))
meses <- c(5, 8)
todos <- cbind(meses, month(fechas))
Manejo de Ruido por Binning: Equal Freq // Equal Width
library(infotheo)
# Discretize recibe el atributo, el método de binning y la cantidad de bins
bin_eq_freq <- discretize(iris$Sepal.Width,"equalfreq", 5)
# Nos copiamos el atributo original
bin_eq_freq$Sepal.Width = iris$Sepal.Width
# Por cada bin calculamos la media y reemplazamos en el atributo suavizado
for(bin in 1:5){
bin_eq_freq$suavizado[ bin_eq_freq$X==bin] = mean(bin_eq_freq$Sepal.Width[ bin_eq_freq$X==bin])
}
# grafico Sepal.Width ordenado de menor a mayor
plot(sort(iris$Sepal.Width,decreasing = FALSE) , type = "l", col="red", ylab = "Sepal.Width")
# Agrego la serie de la variable media
lines(sort(bin_eq_freq$suavizado),type = "l", col="blue")
En datos de tipo cualitativos/nominales: Test de Chi-Cuadrado
Hacemos la tabla de contingencia:
library(MASS)
tbl_cont = table(survey$Smoke, survey$Exer)
print(tbl_cont)
Freq None Some
Heavy 7 1 3
Never 87 18 84
Occas 12 3 4
Regul 9 1 7
Luego aplicamos el Test de Chi-cuadrado:
chisq.test(tbl_cont)
Pearson's Chi-squared test
data: tbl_cont
X-squared = 5.4885, df = 6, p-value = 0.4828
En datos de tipo cuantitativos/numéricos: Coeficiente de Correlación & Covarianza
llamadas=read.csv('llamadas.csv')
cor(llamadas$minutos,llamadas$unidades) # Coeficiente de Pearson
[1] 0.9936987
Debemos recordar validar los supuestos para una regresión -a menudo, esto no aparece en la Bibliografía-
plot(llamadas$minutos,llamadas$unidades) # Gráficamente