El siguiente informe nace como parte de las actividades de la asignatura Estadistica Avanzada del Master en Data Science en la Universitat Oberta de Catalunya, con esto busco ofrecer un blog personal de informes que permitan evidenciar el crecimiento académico que se puede ir adquiriendo con el paso del Master y como R Studio es una herramienta de gran uso.

Es de resaltar que mi primer contacto con el Software R se da en este trabajo, por lo que soy consciente de que existen mejores ténicas para el uso de este, las cuales iran reflejandose con el paso de los informes.

Descripción Set de Datos

Los datos a tratar corresponden a una investigación médica orientada a estudiar la capacidad pulmonar de las personas en función de si eran fumadoras o no. A cada persona, se le preguntó, a través de un cuestionario, su género, edad, hábitos de deporte, la ciudad de residencia, si era fumadora, y en caso de que lo fuera, cuántos cigarrillos al día de promedio fumaba y los años que hacía que fumaba. Además, se midió el peso, la altura y la capacidad pulmonar a partir de un test de aire expulsado, desde donde se tomó como capacidad pulmonar la medida FEF (forced expiratory flow), que es la velocidad del aire saliendo del pulmón durante la porción central de una espiración forzada. Se mide en litros / segundo.

El archivo se denomina Fumadores_raw.csv, contiene 300 registros y 9 variables. Estas variables son: Sex, Sport, Years, Cig, PC, City, Weight, Age, Height.

Desrcargar Set

Preprocesando datos desde un archivo csv

El objetivo concreto es preparar el archivo para su posterior análisis. A continuación se realizará un paso a paso de de la fuente de datos.

Carga del archivo y Descripción

Recuerda inspeccionar previamente el archivo con un editor de texto para identificar el tipo de separador.

Carga del Archivo

archivo<- read.csv("Fumadores_raw.csv", sep=",",na.strings = "NA")
archivo<-as.data.frame(archivo) #

El archivo cuenta con 300 observaciones y 9 variables (Sex, Sport, Years, Cig, PC, City, Weight, Age, Height).

Para escribir código r en línea, debes escribir entre ``: r y la función que quieras invocar. Por ejemplo, para saber cuantos registros existen se escribe: r nrow(archivo), cantidad de variables: r length(archivo) y nombres de las variables: r names(archivo)

A continuación se presenta una impresión de los 6 primeros registros del archivo

Datos

  head(archivo)

Identificar el tipo de variable (Clase):

En este apartado se indica el tipo de variables estadística, es decir la clase a la que pertenece cada variable.

Tipos de Variables

Variable Tipo de Dato Tipo Estadistico
Sex factor Cualitativa
Sport integer Cuantitativa
Years integer Cuantitativa
Cig integer Cuantitativa
PC factor Cualitativa
City factor Cualitativa
Weight integer CUantitativa
Age integer Cuantitativa
Height integer Cuantitativa

Asignación del tipo de variable correcto:

Como se puede observar en el tipo de dato, R no ha asignado el tipo de dato apropiado, por lo que a continuación procedemos a asignarlo:

PC

pc_column<- archivo$PC #carga de columna especifica
pc_column<- sub(',', '\\.', pc_column) #sustitucion de comas por puntos
pc_column<- as.numeric(pc_column) # Cambio de Formato a numerico
pc_column<- format(round(pc_column, 3), nsmall = 3) #Redondeo a 3 decimales
pc_column<- as.numeric(pc_column) # Reformateo a numerico
archivo$PC<-pc_column  # actualizacion de datos del dataframe original
class(archivo$PC) # Clase
## [1] "numeric"
summary(pc_column) #Resumen estadistico de la variable
##    Min. 1st Qu.  Median    Mean 3rd Qu.    Max.    NA's 
##   1.557   2.913   3.554   3.331   3.794   4.466       2

City

archivo$City<-as.character(archivo$City) # Transformando el tipo a character
class(archivo$City) #verificando la clase
## [1] "character"

Sport

archivo$Sport<- factor(archivo$Sport) # Transformando el tipo a factor
class(archivo$Sport)  #verificando la clase
## [1] "factor"

Normalizando / Estandarizando variables cuantitativas.

Es habitual que en el tratamiento de datos algunas de las variables presentan ciertas inconsistencias, como por ejemplo un ingreso ecónomico en dolares y pesos; el peso de un grupo de personas con valores en libras y kilos; la altura de un grupo de personas en metros y centimetros. Por lo general, los sistemas transaccionales buscan disminuir este tipo de errores, sin embargo, en nuestro caso encontramos la variable Weight con una variación bastante extrema, permitiendo identificar que algunos valores estan en unidades diferentes. A continuación, procedemos a normalizar estos a través de una función denominada gram2kilogram(peso), la cual recibe una variable peso y valida si es kilo o gramo a través de una condicional, una vez validado procede a operar aritmeticamente el valor si este esta en gramos, retornando el valor en kilo.

Weight

#Funcion para limpiar variable con valores en miles
#Para esta funcipon, partimos de la premisa que ningún ser humano puede pesar 1000 kilogramos.
gram2Kilogram<- function(peso){
  if(peso > 1000){ #comprueba si el valor es mayor a mil, de serlo, estará en gramos.
    peso = peso/1000 # transforma a kilos
    return(peso) #retorna el peso en kilos
  } else{
    return(peso) # si no es mayor a 1000 es porque este se encuentra en kilos.
  }
}

weight_column<- archivo$Weight #carga de columna especifica
boxplot(weight_column, main="Box Plot Weight Error Values", col="green") # Grafico para conocer la representacion de los datos con outliers

summary(weight_column) #resumen de la variable
##    Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
##      57      65      68    4673      71   74000

Procedemos a normalizar la variable weight y obtenemos:

for (i in 1:length(weight_column)) { # bucle para recorrer cada uno de los valores de Weight
    weight_column[i]<- gram2Kilogram(weight_column[i])
}
boxplot(weight_column, main="Box Plot Weight Fixed", col="blue") # Grafico para verificar la distribucion de los datos corregidos

archivo$Weight<- weight_column # actualizacion de datos del dataframe original

Como se puede observar en el grafico anterior, se han normalizado los valores de la variable weight a tarvés de una división sobre valores mayores a 1000.

Normalizando / Estandarizando variables cualitativas.

Normalizar / Estandarizar variables cualitativas.

City

library(lettercase)
library(stringi)
city_column<-archivo$City
head(city_column) # Verificando Inconsistencias
## [1] "Barcelona"             "  Terrassa"            "  La Bisbal"          
## [4] "Blanes   "             "Sant Boi de Llobregat" "  Barcelona"
city_column<- str_ucfirst(city_column) # Colocar en mayuscula la primer letra
city_column<-trimws(city_column) #  eliminacion de espacios en blanco
city_column<-iconv(city_column, to="ASCII//TRANSLIT") # Eliminar acentos
archivo$City<-city_column # actualizacion de datos del dataframe original
head(city_column) # Previsualizacion de datos corregidos
## [1] "Barcelona"             "Terrassa"              "La Bisbal"            
## [4] "Blanes"                "Sant Boi De Llobregat" "Barcelona"

Sex

library(stringr)
sex_column<- archivo$Sex # Verificando Inconsistencias 
levels(sex_column) # Categorias erroneas
##  [1] "  f"    "  F"    "  f   " "  F   " "  m"    "  M"    "  m   "
##  [8] "  M   " "f"      "F"      "f   "   "F   "   "m"      "M"     
## [15] "m   "   "M   "
sex_column<-as.character(sex_column) # casteo de la variable a caracter
sex_column<-str_delete_whitespace(sex_column) # eliminacion de espacios en blanco
archivo$Sex<-as.factor(str_all_caps(sex_column)) # actualizacion de datos del dataframe original con funcion de mayusculas
levels(archivo$Sex) # Previsualizacion de datos corregidos
## [1] "F" "M"

Sport

sport_column<- archivo$Sport
head(sport_column) # impresion de registros de la variable sport
## [1] 1 1 4 2 1 4
## Levels: 1 2 3 4
#Asignando nombres a cada uno de los niveles
sport_column<- factor(archivo$Sport, levels=c(1,2,3,4),labels=c("None","Sometimes","Regularly","Every Day")) 
head(sport_column)
## [1] None      None      Every Day Sometimes None      Every Day
## Levels: None Sometimes Regularly Every Day
archivo$Sport<- sport_column # asignando la variable trasnformada de nuevo al set de datos

Revisando posibles inconsistencias entre variables: Years vs Cig:

Como es mencionado en la descripcion de la fuente de datos, years indica cuanto tiempo en años lleva fumando uno de los entrevistados, por lo que si Cig (cigarrillos al día) es igual a cero, years debería ser 0. La anterior situación queda expuesta en el siguiente grafico, donde se puede observar que para valores de CIG en 0, existen valores mayores a 0 en YEAR.

plot(archivo$Cig,archivo$Years,  main= "Years vs Cig", xlab="CIG", ylab="PC", pch=19, col="blue") #mostrando el error

for (i in 1:length(archivo$Cig)) { # Normalizando years en cero y cig en cero
   if(archivo$Cig[i]==0)
   {
     archivo$Years[i]<-0
   }else if(archivo$Years[i]==0){
     archivo$Cig[i]<-0
   }
}
plot(archivo$Cig,archivo$Years,  main= "Years vs Cig Fixed", xlab="CIG", ylab="PC", pch=19, col="green") #mostrando el error

#

Procedemos a corregir dicha anomalía:

plot(archivo$Cig,archivo$Years,  main= "Years vs Cig Fixed", xlab="CIG", ylab="PC", pch=19, col="green") #mostrando el error

Valores atípicos en variables cuantitativas:

La mejor forma de identificar los valores atípicos (outlier) en variables cuantitativas es a través de un boxplot, ya que en este podemos identificar como estan representados los datos con respecto a sus métricas descriptivas (media, mediana, cuartiles):

Years

boxplot(archivo$Years, main="Box Plot Years", col="gray")

Cig

boxplot(archivo$Cig, main="Box Plot Cig", col="purple")

PC

boxplot(archivo$PC, main="Box Plot PC", col="pink")

Weight

boxplot(archivo$Weight, main="Box Plot Weight", col="yellow")

Age

boxplot(archivo$Age, main="Box Plot Age", col="red")

Height

boxplot(archivo$Height, main="Box Plot Height", col="blue")

Ahora, procedemos a realizar las estimaciones robustas y no robustas de tendencia central y dispersión para cada variable cuantitativa.

library(psych)
Variable Media Aritmetica Mediana Media Recortada Media Winsorizada Desviacion Estandar
Years 8.4633333 0 7.0148148 8.1133333 12.5416492
Cig 7.2733333 0 6.1111111 7.05 10.4134571
PC 3.3314664 3.554 3.3571926 3.3342634 0.6283275
Weight 67.7166667 68 67.7333333 67.71 3.828653
Age 45.5866667 46 45.4925926 45.5433333 10.6269593
Height 171.4366667 172 171.4740741 171.4266667 5.7436301
Variable RIC DAM
Years 15.25 0
Cig 13 0
PC 0.88075 0.541149
Weight 6 4.4478
Age 14 10.3782
Height 10 7.413

Tratamiento de Valores perdidos

Identificacion de variables con valores perdidos:

colSums(is.na(archivo))
##    Sex  Sport  Years    Cig     PC   City Weight    Age Height 
##      0      0      0      0      2      0      0      0      0

Como se puede evidenciar, PC presenta un total de 2 observaciones con valores perdidos.

Imputación de valores a partir de KNN

En este apartado se ha usado KNN como algoritmo para imputar los valores perdidos a través de la medición de distancias Gower entre cada valor de la variable

#Missing Value
library(VIM)
archivo<- kNN(archivo) 
archivo<-subset(archivo, select = Sex:Height) 
archivo$PC<-as.numeric(archivo$PC)
colSums(is.na(archivo))
##    Sex  Sport  Years    Cig     PC   City Weight    Age Height 
##      0      0      0      0      0      0      0      0      0

Como se puede obervar en el conteno de valores NA en la variable PC, esta ha sido imputada a partir de KNN con un k por defecto.

Resumen descriptivo de los datos depurados:

Se realiza un resumen estadistico - descriptivo de cada una de las columnas depuradas, entre las métricas estan: MINIMOS, MAXIMOS , Rango Intercuartilico (RIC) y Media

Variables Cuantitativas

#library(pastecs)
#stat.desc(archivo$Years)
Variable Minimos Maximos RIC Media
Years 0 51 15.25 8.4633333
Cig 0 47 13 7.2733333
PC 1.557 4.466 0.88475 3.33099
Weight 57 79 6 67.7166667
Age 19 77 14 45.5866667
Height 158 186 10 171.4366667

Variables Cualitativas

Sex
table(archivo$Sex)
## 
##   F   M 
## 137 163
Sport
table(archivo$Sport)
## 
##      None Sometimes Regularly Every Day 
##       127        83        48        42
City
table(archivo$City)
## 
##               Alcanar             Barcelona                Blanes 
##                    12                   102                    11 
##              Cadaques              Cardedeu               Cardona 
##                     2                     3                     6 
##                Girona             La Bisbal                Lleida 
##                    10                     7                    13 
##               Montgat         Pineda De Mar             Puigcerda 
##                     6                    11                     3 
##                Ripoll Sant Boi De Llobregat                Sitges 
##                     6                    12                    13 
##               Solsona             Tarragona              Terrassa 
##                     5                    14                    42 
##                 Tossa                 Valls 
##                     7                    15

Creación del archivo de salida

Una vez se han depurado todas las variables, se genera el archivo con los datos:

# Write CSV 
write.table(archivo, file = "fichero_clean.csv",row.names=FALSE, na="",col.names=TRUE, sep=",")
# row.names indica el nombre de cada fila, no es nuestro caso, pero podríamos asignarles ids
# na indica al archivo que si existen valores nulos los deje en vacio
# col.names indica el nombre de las columnas como cabecera en el archivo
# sep indica el tipo de separador con que registraran los datos en el archivo csv

Anexos

Tipos de Variables

Variable Tipo de Dato Tipo Estadistico
Sex factor Cualitativa
Sport factor Cualitativa
Years numeric Cuantitativa
Cig numeric Cuantitativa
PC numeric Cuantitativa
City character Cualitativa
Weight numeric CUantitativa
Age integer Cuantitativa
Height integer Cuantitativa

Sex

barplot(prop.table(table(archivo$Sex)), main="Distribucion Sex", xlab="Personas", col=c("red","blue"),legend.text=c("Femeninno","Masculino"), ylim=c(0,0.8), ylab ="Frecuencias Relativas",las=1)

Sport

barplot(prop.table(table(archivo$Sport)), main="Distribucion Sport", xlab="Personas", col=c("green","blue", "red", "yellow"),legend.text=c("None","Sometimes","Regularly","Every Day"), ylim=c(0,0.8), ylab ="Frecuencias Relativas",las=1, legend = rownames(archivo$Sport))

City

barplot(prop.table(table(archivo$City)), main="Distribucion City", xlab="Ciudades",legend.text=levels(archivo$City),ylim=c(0,0.8), ylab ="Frecuencias Relativas",las=1, , legend = rownames(archivo$Sport))