#la tabla esta en UCI repositario de bases de datos
#CSV formato tabular separado por comas
#En files se establece la ruta de trabajo
#En Global environment se da click en la brochita para limpiar el fichero
datos<-read.table("http://archive.ics.uci.edu/ml/machine-learning-databases/heart-disease/processed.cleveland.data", sep=",")
View(datos)
#nombres de las variables
#no hay nombres porque es un CSV
names(datos)
## [1] "V1" "V2" "V3" "V4" "V5" "V6" "V7" "V8" "V9" "V10" "V11"
## [12] "V12" "V13" "V14"
#Dimension de la tabla
dim(datos)
## [1] 303 14
#visualizar los primeros datos en la tabla
head(datos)
## V1 V2 V3 V4 V5 V6 V7 V8 V9 V10 V11 V12 V13 V14
## 1 63 1 1 145 233 1 2 150 0 2.3 3 0.0 6.0 0
## 2 67 1 4 160 286 0 2 108 1 1.5 2 3.0 3.0 2
## 3 67 1 4 120 229 0 2 129 1 2.6 2 2.0 7.0 1
## 4 37 1 3 130 250 0 0 187 0 3.5 3 0.0 3.0 0
## 5 41 0 2 130 204 0 2 172 0 1.4 1 0.0 3.0 0
## 6 56 1 2 120 236 0 0 178 0 0.8 1 0.0 3.0 0
#visualizar un rango de datos que van de la fila 10:15 con todas las columnas
datos[10:15,]
## V1 V2 V3 V4 V5 V6 V7 V8 V9 V10 V11 V12 V13 V14
## 10 53 1 4 140 203 1 2 155 1 3.1 3 0.0 7.0 1
## 11 57 1 4 140 192 0 0 148 0 0.4 2 0.0 6.0 0
## 12 56 0 2 140 294 0 2 153 0 1.3 2 0.0 3.0 0
## 13 56 1 3 130 256 1 2 142 1 0.6 2 1.0 6.0 2
## 14 44 1 2 120 263 0 0 173 0 0.0 1 0.0 7.0 0
## 15 52 1 3 172 199 1 0 162 0 0.5 1 0.0 7.0 0
# Exploramos la parte final de los datos (veremos que aparece ?)
tail(datos)
## V1 V2 V3 V4 V5 V6 V7 V8 V9 V10 V11 V12 V13 V14
## 298 57 0 4 140 241 0 0 123 1 0.2 2 0.0 7.0 1
## 299 45 1 1 110 264 0 0 132 0 1.2 2 0.0 7.0 1
## 300 68 1 4 144 193 1 0 141 0 3.4 2 2.0 7.0 2
## 301 57 1 4 130 131 0 0 115 1 1.2 2 1.0 7.0 3
## 302 57 0 2 130 236 0 2 174 0 0.0 2 1.0 3.0 1
## 303 38 1 3 138 175 0 0 173 0 0.0 1 ? 3.0 0
#los autores han decidido poner ? para info NA (no disponible)
# -- Opción 1: eliminar las filas con ? --
# Encontrarlas los strings siempre van entre comillas (sen o dobles)
#datos es el nombre de nuestra tabla, arr=array, ind=indice
which(datos=='?', arr.ind=T)
## row col
## [1,] 167 12
## [2,] 193 12
## [3,] 288 12
## [4,] 303 12
## [5,] 88 13
## [6,] 267 13
# Eliminarlas
#aborrar se define como la función que nos ayudo a encontrar ? y definimos un vector con las filas
aborrar<-which(datos=='?', arr.ind=T)[,1]
aborrar
## [1] 167 193 288 303 88 267
#usando una resta eliminamos las filas que tenían ?
datosn1<-datos[-aborrar,]
#comprobando eliminación
dim(datos)
## [1] 303 14
dim(datosn1)
## [1] 297 14
tail(datosn1)
## V1 V2 V3 V4 V5 V6 V7 V8 V9 V10 V11 V12 V13 V14
## 297 59 1 4 164 176 1 2 90 0 1.0 2 2.0 6.0 3
## 298 57 0 4 140 241 0 0 123 1 0.2 2 0.0 7.0 1
## 299 45 1 1 110 264 0 0 132 0 1.2 2 0.0 7.0 1
## 300 68 1 4 144 193 1 0 141 0 3.4 2 2.0 7.0 2
## 301 57 1 4 130 131 0 0 115 1 1.2 2 1.0 7.0 3
## 302 57 0 2 130 236 0 2 174 0 0.0 2 1.0 3.0 1
#tratando de ver el dato 288 que contenia ? en ambas datos y datosn1
#en datosn1 ya no encontraremos 288 porque al eliminar los datos con ?
#el orden de los elementos cambio, el array enumera por aparición
datos[286:292,]
## V1 V2 V3 V4 V5 V6 V7 V8 V9 V10 V11 V12 V13 V14
## 286 58 1 4 114 318 0 1 140 0 4.4 3 3.0 6.0 4
## 287 58 0 4 170 225 1 2 146 1 2.8 2 2.0 6.0 2
## 288 58 1 2 125 220 0 0 144 0 0.4 2 ? 7.0 0
## 289 56 1 2 130 221 0 2 163 0 0.0 1 0.0 7.0 0
## 290 56 1 2 120 240 0 0 169 0 0.0 3 0.0 3.0 0
## 291 67 1 3 152 212 0 2 150 0 0.8 2 0.0 7.0 1
## 292 55 0 2 132 342 0 0 166 0 1.2 1 0.0 3.0 0
datosn1[286:292,]
## V1 V2 V3 V4 V5 V6 V7 V8 V9 V10 V11 V12 V13 V14
## 291 67 1 3 152 212 0 2 150 0 0.8 2 0.0 7.0 1
## 292 55 0 2 132 342 0 0 166 0 1.2 1 0.0 3.0 0
## 293 44 1 4 120 169 0 0 144 1 2.8 3 0.0 6.0 2
## 294 63 1 4 140 187 0 2 144 1 4.0 1 2.0 7.0 2
## 295 63 0 4 124 197 0 0 136 1 0.0 2 0.0 3.0 1
## 296 41 1 2 120 157 0 0 182 0 0.0 1 0.0 3.0 0
## 297 59 1 4 164 176 1 2 90 0 1.0 2 2.0 6.0 3
datosn1[280:291,]
## V1 V2 V3 V4 V5 V6 V7 V8 V9 V10 V11 V12 V13 V14
## 284 35 1 2 122 192 0 0 174 0 0.0 1 0.0 3.0 0
## 285 61 1 4 148 203 0 0 161 0 0.0 1 1.0 7.0 2
## 286 58 1 4 114 318 0 1 140 0 4.4 3 3.0 6.0 4
## 287 58 0 4 170 225 1 2 146 1 2.8 2 2.0 6.0 2
## 289 56 1 2 130 221 0 2 163 0 0.0 1 0.0 7.0 0
## 290 56 1 2 120 240 0 0 169 0 0.0 3 0.0 3.0 0
## 291 67 1 3 152 212 0 2 150 0 0.8 2 0.0 7.0 1
## 292 55 0 2 132 342 0 0 166 0 1.2 1 0.0 3.0 0
## 293 44 1 4 120 169 0 0 144 1 2.8 3 0.0 6.0 2
## 294 63 1 4 140 187 0 2 144 1 4.0 1 2.0 7.0 2
## 295 63 0 4 124 197 0 0 136 1 0.0 2 0.0 3.0 1
## 296 41 1 2 120 157 0 0 182 0 0.0 1 0.0 3.0 0
# -- Opción 2: al cargar los valores indicarle al sistema que los trate como NA
#usando la función na.strings y le indicamos que el valor es '?'
datos<-read.table("http://archive.ics.uci.edu/ml/machine-learning-databases/heart-disease/processed.cleveland.data", sep=",", na.strings=c("?"))
# ... y después omitimos los valores NA
datosn1<-na.omit(datos)
#comprobamos
dim(datos)
## [1] 303 14
dim(datosn1)
## [1] 297 14
#IMPORTANTE:Solo hay que limpiar las variables que vamos a analizar para nuestro proyecto.
#estos tratamientos los hace como instrucción a objetos
# Podemos hacer que la columna de sexo y diabetes sea un factor
#factor son valores categóricos que se miden en niveles
#defino que ocupo el vector v2 de la tabla datos, indico los valores en la columna e indico etiquetas
#alineadas a los valores en el vector
datos$V2<-factor(datos$V2, levels=c(0,1), labels=c('Mujer', 'Hombre'))
datos$V6<-factor(datos$V6, levels=c(0,1), labels=c('No', 'Si'))
# Agrupar los niveles de la columna de enfermedad (enfermo si valor > 0)
#si el paciente esta enfermo la columna tiene un valor positivo entero
#indicamos la tabla, la variable de interés,abrimos conchetes indicando un rango, mayor que cero y definimos =1
datos$V14[datos$V14>0]<-1
# Convertir en factor la columna de enfermedad (con valores pos -enfermo- o neg -no enfermo-)
datos$V14<-factor(datos$V14, levels=c(0,1), labels=c('Neg', 'Pos'))
# Creamos un data frame reducido a las columnas de interés
#al nombrarlos aparecen en el global environment con las caracteristicas
#indicadas en los pasos anteriores
edad<-datos$V1
sexo<-datos$V2
tension<-datos$V4
colesterol<-datos$V5
diabetes<-datos$V6
diagnostico<-datos$V14
#nuestra tabla es de 303 obs y 6 variables, col12 y col13 no se ocuparon, no hay '?'
d<-data.frame(edad,sexo,tension,colesterol,diabetes,diagnostico)
#funcion head nos muestra las primeras 6 filas de nuestra tabla
head(d)
## edad sexo tension colesterol diabetes diagnostico
## 1 63 Hombre 145 233 Si Neg
## 2 67 Hombre 160 286 No Pos
## 3 67 Hombre 120 229 No Pos
## 4 37 Hombre 130 250 No Neg
## 5 41 Mujer 130 204 No Neg
## 6 56 Hombre 120 236 No Neg
# Una vez tenemos los datos, comenzamos el análisis
# 1) Estadísticas del dataset
# la función summary da detalle de las estadísticas principales del data frame
summary(d)
## edad sexo tension colesterol diabetes
## Min. :29.00 Mujer : 97 Min. : 94.0 Min. :126.0 No:258
## 1st Qu.:48.00 Hombre:206 1st Qu.:120.0 1st Qu.:211.0 Si: 45
## Median :56.00 Median :130.0 Median :241.0
## Mean :54.44 Mean :131.7 Mean :246.7
## 3rd Qu.:61.00 3rd Qu.:140.0 3rd Qu.:275.0
## Max. :77.00 Max. :200.0 Max. :564.0
## diagnostico
## Neg:164
## Pos:139
##
##
##
##
#la funcion mean para obtener media del dato edad, no acepta calcular otro valor mean(d$edad,d$tension)
mean(d$edad)
## [1] 54.43894
#la funcion median para la mediana, no acepta calcular otro valor.
median(d$edad)
## [1] 56
#la desviación estándar que es la medida de desviación con respecto a la media de la variable
sd(d$colesterol)
## [1] 51.77692
#los breaks son los intervalos en la distribucion
#el eje "y"(altura) es la frecuencia de la observacion
#el eje "x" (ancho) es la distribución de edades
#la edad se "distribuye normalmente" ligeramente sesgada a la derecha
#esto significa que la mayoría de las obs se concentran en el centro
#y tenemos pocos datos en los extremos de la distribución.
hist(d$edad, breaks=10)

hist(d$edad, breaks=20)

#esta caja hace referencia a la información que vemos con la funcion summary
#el valor mínimo esta en la línea de hasta abajo (29), el valor maximo en la última línea (77)
#la línea negra dentro de la caja señala el valor medio (54)
#las líneas de las cajas indican los cuartiles, primer cuartil (48) y tercer cuartil (61)
boxplot(d$edad)

# 3) Diagrama de caja de la distribución de colesterol por sexo
#nos ayuda a inferir la respuesta a la pregunta de si el colesterol y el sexo están relacionados
boxplot(colesterol ~ sexo, data=d)

#la media entre hombres y mujeres es diferente
#las mujeres presentan mayor dispersión en los valores de colesterol (distancia entre media y valores min y max)
#las mujeres presentan un valor "outlier" que se representan con un punto en la parte final.
#================================
# 5) Chi square
# Sexo y diabetes son o no son variables independientes?
# Hipotesis nula: son independientes
# Creamos la tabla de contingencia que solo puede existir cuando se tienen
# valores categóricos
tabla<-table(d$sexo, d$diabetes)
tabla
##
## No Si
## Mujer 85 12
## Hombre 173 33
chisq.test(tabla)
##
## Pearson's Chi-squared test with Yates' continuity correction
##
## data: tabla
## X-squared = 0.43559, df = 1, p-value = 0.5093
#p-value valor dentro del intervalo de confianza del 95% a un nivel de significancia del 5%
#si el valor del pi-value es más pequeño que el nivel de significancia, la ho es rechazada.
#esto es cierto para un modelo de regresión lineal.
#un pi value de 0.08 puede ser rechazado a un nivel de significancia de 10%, pero no a uno de 5%
#0.1>0.08>0.05
#la hipotesis nula no se puede rechazar, parecen ser independientes
# Sexo y enfermedad cardiovascular son independientes?
# Hipótesis nula: son independientes
tabla<-table(d$sexo, d$diagnostico)
tabla
##
## Neg Pos
## Mujer 72 25
## Hombre 92 114
chisq.test(tabla)
##
## Pearson's Chi-squared test with Yates' continuity correction
##
## data: tabla
## X-squared = 22.043, df = 1, p-value = 2.667e-06
#en este caso el valor del p-value es muy pequeño a un nivel de significancia del 5%
#la hipotesis nula se rechaza, son dependientes
# El test t-student es para identificar si dos medias son
#significativamente diferentes o no.
# 6) Las medias de colesterol de hombres y mujeres son las mismas
# Hipotesis nula: tiene la misma medio o que la diferencia de medias es 0
t.test(d[d$sexo=="Hombre",]$colesterol, d[d$sexo=="Mujer",]$colesterol)
##
## Welch Two Sample t-test
##
## data: d[d$sexo == "Hombre", ]$colesterol and d[d$sexo == "Mujer", ]$colesterol
## t = -3.0643, df = 136.37, p-value = 0.002631
## alternative hypothesis: true difference in means is not equal to 0
## 95 percent confidence interval:
## -36.445477 -7.855795
## sample estimates:
## mean of x mean of y
## 239.6019 261.7526
#el valor de p-value es pequeño por lo que se rechaza la hipotesis nula de
#que la diferencia de medias es cero, esto lo pudimos inferir visualmente en
#el diagrama de caja donde comparamos colesterol en hombres y mujeres
#================================
# 7) Existe correlación entre edad y colesterol
# nos indicaría la relación que existe entre edad y colesterol
# corr pos.a mayor edad, mayor colesterol, viceversa.
#corr beg. a mayor edad, menor colesterol, viceversa.
cor.test(d$edad, d$colesterol)
##
## Pearson's product-moment correlation
##
## data: d$edad and d$colesterol
## t = 3.707, df = 301, p-value = 0.0002496
## alternative hypothesis: true correlation is not equal to 0
## 95 percent confidence interval:
## 0.09859353 0.31423005
## sample estimates:
## cor
## 0.2089503
cor.test(d$tension, d$colesterol)
##
## Pearson's product-moment correlation
##
## data: d$tension and d$colesterol
## t = 2.2769, df = 301, p-value = 0.0235
## alternative hypothesis: true correlation is not equal to 0
## 95 percent confidence interval:
## 0.0177016 0.2392898
## sample estimates:
## cor
## 0.1301201
#un valor de p muy pequeño que nos hace rechazar la hipotesis nula
#cuando aumenta la edad, aumenta el nivel de colesterol
#corr tiene un valor entre 0 y 1 que indica que la fuerza de la correlación
#entre más cercano a 1 es la correlación es más fuerte.
#en este caso, la correlación no es muy fuerte y es positiva.
#variable dependiente=colesterol var.independiente=edad
#el modelo sería colesterol=a+b*edad+u (a=intercepto u=error)
modelo<-lm(colesterol ~ edad, data=d)
summary(modelo)
##
## Call:
## lm(formula = colesterol ~ edad, data = d)
##
## Residuals:
## Min 1Q Median 3Q Max
## -123.759 -32.600 -5.804 28.628 302.272
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) 181.5325 17.8176 10.188 < 2e-16 ***
## edad 1.1969 0.3229 3.707 0.00025 ***
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 50.72 on 301 degrees of freedom
## Multiple R-squared: 0.04366, Adjusted R-squared: 0.04048
## F-statistic: 13.74 on 1 and 301 DF, p-value: 0.0002496
plot(modelo)




#b=1.1969 es el efecto de la edad sobre el colesterol
#el intercepto es el valor inicial del colesterol cuando no es explicado por la edad.
#el valor de los residuales es 50.72 es el error en el ajuste
#el valor de ADJUSTED R-SQUARED no es muy bueno, estamos buscando un num cercano al 1
#mas cercano a 1, mejor el ajuste del modelo lineal.
#cuando le pedimos que gráfique el modelo se puede ver que el ajuste
#no es bueno.
model<-lm(colesterol~tension, data=d)
summary(model)
##
## Call:
## lm(formula = colesterol ~ tension, data = d)
##
## Residuals:
## Min 1Q Median 3Q Max
## -127.70 -33.24 -5.27 28.66 323.70
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) 196.2820 22.3369 8.787 <2e-16 ***
## tension 0.3828 0.1681 2.277 0.0235 *
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 51.42 on 301 degrees of freedom
## Multiple R-squared: 0.01693, Adjusted R-squared: 0.01367
## F-statistic: 5.184 on 1 and 301 DF, p-value: 0.0235
plot(model)




#este modelo esta aun peor ajustado
#================================
# Entrenamos con una parte de los datos
#utilizamos una librería externa
library(e1071)
## Warning: package 'e1071' was built under R version 3.4.1
#grupo de entrenamiento
train<-d[1:250,]
#un modelo probabilistico basado en el teorema de bayes donde nos indique
#la prob de que el diagnostico sea positivo o negativo con base en
#los datos de colesterol, tension, edad y diabetes
clasificador<-naiveBayes(diagnostico ~ colesterol + tension + edad + diabetes, data=train)
#este es un modelo muy sencillo de whole-out en el que hemos seleccionado manualmente nuestro
#grupo de entrenamiento y después seleccionamos la evaluación
# Y evaluamos con la otra parte
eval<-d[251:303,]
diagnostico<-eval[,6]
diagnostico
## [1] Neg Pos Neg Neg Neg Neg Neg Neg Neg Pos Neg Pos Neg Neg Pos Pos Pos
## [18] Pos Pos Neg Pos Neg Pos Neg Pos Neg Neg Neg Pos Neg Pos Neg Pos Neg
## [35] Pos Pos Pos Neg Neg Neg Pos Neg Pos Pos Pos Neg Pos Pos Pos Pos Pos
## [52] Pos Neg
## Levels: Neg Pos
#predecir el valor de la evaluación a partir de la información de lo que definimos
#en nuestro clasificador
predicted<-predict(clasificador, eval[,-6])
#¿que tan bueno es mi clasificador?
#esta matriz me permite calcular el accuracy del clasificador, es decir
#la precisión del clasificador versus la evaluación
#los valores correctos está en la diagonal principal
matrizconf<-table(predicted, diagnostico)
matrizconf
## diagnostico
## predicted Neg Pos
## Neg 18 16
## Pos 8 11
#en mi diagnostico hay 18 negativos que son correctos y 16 que no (Es un falso negativo)
sum(diag(matrizconf))/sum(matrizconf)
## [1] 0.5471698
#el accuracy de este modelo es de 55%, es malo porque hay un 55% de posibilidad que
#sea malo o sea bueno. Tampoco queremos un modelo con accuracy 100% porque indicaría
#otro problema.