-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathPracticaAC.Rmd
More file actions
2496 lines (1830 loc) · 111 KB
/
PracticaAC.Rmd
File metadata and controls
2496 lines (1830 loc) · 111 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
---
title: "Análisis de Datos y Machine Learning con R (Caret)"
author: ["Eva Pina Dubovtseva (G1.4)", "Jesús Sánchez Pardo(G1.5)", "Jiahui Lin(G1.2)"]
output:
pdf_document:
toc: TRUE
toc_depth: 5
number_sections: true
date: "10-12-2024"
editor_options:
markdown:
wrap: 72
---
```{r setup, include=FALSE}
knitr::opts_chunk$set(echo = TRUE)
#Cargar el espacio de trabajo
load("ProyectoAC.Rdata")
```
\newpage
# Librerías empleadas
```{r librerías, message=FALSE}
library(lattice)
library(GGally)
library(ggplot2)
library(reshape2)
library(gridExtra)
library(caret)
library(mlbench)
library(rpart)
library(rpart.plot)
library(nnet)
library(randomForest)
library(gbm)
library(NeuralNetTools)
library(tidyr)
library(dplyr)
require(plotrix)
```
# Análisis Explotario de Datos
## Carga del dataset
Lo primero de todo, vamos a cargar en la variable "credit" todo el dataset.
```{r carga-datos}
# Cargar dataset
credit <- read.table("crx.data", sep=",", header=FALSE, na.strings="?")
```
## División en Train y Test
Para poder entrenar los modelos, es **esencial** **dividir los datos** que
tenemos **en un conjunto de entrenamiento**, **y otro de test**
para evaluarlo en el modelo final.
Se van a utilizar unos índices preestablecidos para ello.
```{r division}
# Dividimos el dataset en train y test
credit.trainIdx <- readRDS("credit.trainIdx.rds")
credit.Datos.Train <- credit[credit.trainIdx, ]
credit.Datos.Test <- credit[-credit.trainIdx, ]
```
Vamos a visualizar el dataset entero:
```{r visualizacion-inicial}
# Estructura del dataset
head(credit)
```
Como podemos ver, consta de 16 columnas. **Al estar codificado, es complicado**
**interpretar qué es cada variable**. No obstante, claramente la última columna
(**V16**) está relacionado con si el crédito ha sido aprobado o no. Está última,
**será nuesta columna objetivo a lo largo de toda la práctica**.
Con el comando summary() vamos a tener un resumen estadístico de cada variable.
De esta manera, podremos tener una visión superficial de las características de
los datos con los que estamos trabajando. También lo haremos con
los conjuntos de train y test.
```{r}
summary(credit)
summary(credit.Datos.Train)
summary(credit.Datos.Test)
```
La salida nos muestra que las columnas **V2**, **V3**, **V8**, **V11** y **V15** son numéricas. Para ellas, se han calculado valores como la **media**, la **mediana**, entre otros. Si analizamos bien cada una, podemos destacar:
- **V2**: Tiene valores que varían entre **13.75** y **80.25**. La **mediana** de **28.46** sugiere que los valores están **sesgados hacia la izquierda** (menores valores).
- **V3**: Presenta una **mediana de 2.75** y un máximo de **28.00**, lo que indica que la mayoría de los valores están en un **rango bajo**.
- **V15**: Tiene valores muy amplios, desde **0** hasta **1,000,000.0**, con una **media de 1017.4**. Esto puede indicar la presencia de **outliers**.
Por otro lado, también se observa que **en el conjunto de train, y todo el dataset, hay valores nulos en algunas columnas**. En la siguiente sección, se tratarán estos nulos para poder visualizar y analizar los datos completos, y garantizar que los modelos sean entrenados adecuadamente con el conjunto de train. **El conjunto de test no presenta valores nulos**, por lo que no necesita tratamiento.
Finalmente, se procede a **guardar las columnas numéricas y categóricas**. Utilizando el comando **sapply()**, se aplica la función **is.numeric** o **is.factor** para identificar los tipos de columnas y guardar los resultados en vectores correspondientes.
```{r}
# Identificar tipos de columnas
numeric_columns <- sapply(credit, is.numeric)
categorical_columns <- sapply(credit, is.factor)
# Guardaremos también los nombres de las columnas
numeric_columns2 <- names(credit)[sapply(credit, is.numeric)]
categorical_columns2 <- names(credit)[sapply(credit, function(x) is.character(x) || is.factor(x))]
```
## Tratamiento de valores nulos
Como hemos visto con el summary, tenemos datos nulos. Vamos a tratarlos
primero con tal de tener los datos actualizados a nuestro análisis.
Con el siguiente comando, podemos ver cuántos datos nulos hay en cada
variable.
```{r}
sapply(credit, function(x) sum(is.na(x)))
sapply(credit.Datos.Train, function(x) sum(is.na(x)))
```
Al ser un dataset **no muy grande**, vamos a optar por **rellenar los NAs** con la **mediana** para las variables de valores **numéricos**, y el **más frecuente** si es un **factor**. Además, de que **no son demasiados los valores faltantes**, por lo que el **relleno de los NAs no debería introducir mucho sesgo**.
```{r categorias, fig.width=5, fig.height=3}
# Convertir columnas categóricas a factor
credit[categorical_columns2] <- lapply(credit[categorical_columns2], as.factor)
credit.Datos.Train[categorical_columns2] <- lapply(credit.Datos.Train[categorical_columns2], as.factor)
credit.Datos.Test[categorical_columns2] <- lapply(credit.Datos.Test[categorical_columns2], as.factor)
```
```{r valores-faltantes}
# Número total y por columna de valores faltantes
sum(is.na(credit))
# Rellenar valores faltantes
fixNA_credit <- function(data.toFix) {
for (i in seq_along(data.toFix)) {
if (is.factor(data.toFix[[i]])) {
ttx <- table(data.toFix[[i]], useNA = "no")
data.toFix[[i]][is.na(data.toFix[[i]])] <- names(ttx)[which.max(ttx)]
} else if (is.numeric(data.toFix[[i]])) {
data.toFix[[i]][is.na(data.toFix[[i]])] <- median(data.toFix[[i]], na.rm = TRUE)
}
}
return(data.toFix)
}
# Aplicamos la fórmula en credit y en train
credit <- fixNA_credit(credit)
credit.Datos.Train <- fixNA_credit(credit.Datos.Train)
# Verificar nuevamente valores faltantes
sapply(credit, function(x) sum(is.na(x)))
sapply(credit.Datos.Train, function(x) sum(is.na(x)))
```
Como se puede ver, **ya no quedan nulos en el dataset**, **ni en train**.
## Análisis univariable
Al no conocer nada sobre el conjunto, hemos decidido hacer un análisis de todas las variables para ver la distribución de cada una de ellas y evaluar posibles patrones o comportamientos que puedan influir posteriormente en el comportamiento del modelo.
### Variables Categóricas
```{r, fig.width=5, fig.height=3}
ggplot(credit, aes(x = V1)) +
geom_bar(fill = "skyblue", color = "black") +
labs(title = "Distribución de V1", x = "V1", y = "Frecuencia") +
theme_minimal()
```
- **Observación:** Podemos observar dos niveles (`a` y `b`), donde **`b` tiene una frecuencia bastante mayor que `a`**. Esto apunta a un **desbalance de clases** que **podría hacer que el modelo favorezca a la categoría mayoritaria**. Este sesgo puede resultar en que **no se generalice correctamente** sobre los casos en `a`, lo que **afectaría a la precisión y la fiabilidad**.
```{r, fig.width=5, fig.height=3}
ggplot(credit, aes(x = V4)) +
geom_bar(fill = "skyblue", color = "black") +
labs(title = "Distribución de V4", x = "V4", y = "Frecuencia") +
theme_minimal()
```
- **Observación:** De las tres categorías (`l`, `u`, `y`), **`u` tiene la mayor frecuencia con diferencia** y `l` casi no está representada. La concentración en **`u` sugiere que esta es la categoría representativa**, mientras que las categorías `l` e `y` son casos menos frecuentes o con un comportamiento atípico. **Si `l` es irrelevante o está sesgado, es posible que introduzca ruido** o **imprecisiones en el modelo**, mientras que **`u` podría estar fuertemente correlacionada con la variable objetivo (`V16`)**, opacando a `l` e `y` en la predicción. **Este desbalance podría afectar la precisión del modelo**, pues podría generar **sesgo hacia `u`**.
```{r, fig.width=5, fig.height=3}
ggplot(credit, aes(x = V5)) +
geom_bar(fill = "skyblue", color = "black") +
labs(title = "Distribución de V5", x = "V5", y = "Frecuencia") +
theme_minimal()
```
- **Observación:** Distribución parecida a V4 con **predominancia de `g`** y casi nula presencia de `gg`.
```{r, fig.width=5, fig.height=3}
ggplot(credit, aes(x = V6)) +
geom_bar(fill = "skyblue", color = "black") +
labs(title = "Distribución de V6", x = "V6", y = "Frecuencia") +
theme_minimal()
```
- **Observación:** Presenta múltiples niveles con distribución desigual, donde **`c` es la más dominante con diferencia**, mientras que categorías como **`j` y `r` tienen frecuencias bajas**. La categoría dominante (**`c`**) podría representar **comportamientos más comunes o riesgos identificables**, mientras que las categorías poco comunes (como **`j` y `r`**) podrían ser **casos específicos, erróneos o inusuales**. **La irregularidad de esta variable podría producir ruido a la hora de entrenar el modelo**.
```{r, fig.width=5, fig.height=3}
ggplot(credit, aes(x = V7)) +
geom_bar(fill = "skyblue", color = "black") +
labs(title = "Distribución de V7", x = "V7", y = "Frecuencia") +
theme_minimal()
```
- **Observación:** Similar a **V6**, esta vez podemos ver que la categoría dominante es **`v`**, mientras que variables como **`o`, `z`, `n`, `j` y `dd`** son **minoritarios y casi no tienen frecuencia**. Debido a la diferencia tan clara de frecuencia de las categorías podría generar **imprecisiones a la hora de entrenar el modelo**.
```{r, fig.width=5, fig.height=3}
ggplot(credit, aes(x = V9)) +
geom_bar(fill = "skyblue", color = "black") +
labs(title = "Distribución de V9", x = "V9", y = "Frecuencia") +
theme_minimal()
```
- **Observación:** Aquí vemos que la **V9** está compuesta por dos categorías (**`f`** y **`t`**) donde hay prácticamente **igualdad de elementos en cada categoría**. Esta distribución **equitativa** le convierte en candidato a ser una **variable clave a la hora de entrenar el modelo** porque no generaría mucho sesgo hacia ninguna categoría.
```{r, fig.width=5, fig.height=3}
ggplot(credit, aes(x = V10)) +
geom_bar(fill = "skyblue", color = "black") +
labs(title = "Distribución de V10", x = "V10", y = "Frecuencia") +
theme_minimal()
```
- **Observación:** Similar a **`V9`**, con niveles **`f`** y **`t`** siendo el primero el **mayoritario**. Esta variable también sigue una **distribución bastante equitativa**, aunque no tanto como **V9**. Podría generar **cierto sesgo**.
```{r, fig.width=5, fig.height=3}
ggplot(credit, aes(x = V12)) +
geom_bar(fill = "skyblue", color = "black") +
labs(title = "Distribución de V12", x = "V12", y = "Frecuencia") +
theme_minimal()
```
- **Observación:** Dos niveles (**`f`** y **`t`**), con una **distribución muy similar** y **`f` dominante**. Parecida a las variables **V9** y **V10**.
```{r, fig.width=5, fig.height=3}
ggplot(credit, aes(x = V13)) +
geom_bar(fill = "skyblue", color = "black") +
labs(title = "Distribución de V13", x = "V13", y = "Frecuencia") +
theme_minimal()
```
- **Observación:** Tres niveles (`g`, `p`, y `s`), con **`g` como dominante**. Este podría estar asociada con el **comportamiento general**, mientras que las categorías **`p` y `s` presentan una frecuencia minoritaria**, lo que puede hacerlas **menos útiles**, o que sean **valores atípicos**.
### Variables Numéricas
```{r, fig.width=5, fig.height=3}
# Graficar cada variable numérica individualmente
ggplot(credit, aes(x = V2)) +
geom_histogram(fill = "orange", color = "black", bins = 20, alpha = 0.7) +
labs(title = "Distribución de V2", x = "V2", y = "Frecuencia") +
geom_vline(xintercept = mean(credit$V2), col = "blue") +
geom_vline(xintercept = median(credit$V2), col = "red") +
geom_rug(data=credit, aes(x=V2, y=0), sides="b", position="jitter") +
theme_minimal()
```
- **Observación:** Presenta **asimetría positiva**, con **concentración en valores bajos** y **cola extendida hacia la derecha**. Esto refleja que la **mayoría de los casos son pequeños**, mientras que los **valores altos pueden ser atípicos**.
```{r, fig.width=5, fig.height=3}
ggplot(credit, aes(x = V3)) +
geom_histogram(fill = "orange", color = "black", bins = 20, alpha = 0.7) +
labs(title = "Distribución de V3", x = "V3", y = "Frecuencia") +
geom_vline(xintercept = mean(credit$V3), col = "blue") +
geom_vline(xintercept = median(credit$V3), col = "red") +
geom_rug(data=credit, aes(x=V3, y=0), sides="b", position="jitter") +
theme_minimal()
```
- **Observación:** También presenta **asimetría positiva**, aunque con **mayor concentración en valores bajos**. Al igual que con `V2`, los **valores altos pueden representar casos atípicos**.
```{r, fig.width=5, fig.height=3}
ggplot(credit, aes(x = V8)) +
geom_histogram(fill = "orange", color = "black", bins = 20, alpha = 0.7) +
labs(title = "Distribución de V8", x = "V8", y = "Frecuencia") +
geom_vline(xintercept = mean(credit$V8), col = "blue") +
geom_vline(xintercept = median(credit$V8), col = "red") +
geom_rug(data=credit, aes(x=V8, y=0), sides="b", position="jitter") +
theme_minimal()
```
- **Observación:** Similar a **`V3`**, lo que sugiere un **comportamiento similar**.
```{r, fig.width=5, fig.height=3}
ggplot(credit, aes(x = V11)) +
geom_histogram(fill = "orange", color = "black", bins = 20, alpha = 0.7) +
labs(title = "Distribución de V11", x = "V11", y = "Frecuencia") +
geom_vline(xintercept = mean(credit$V11), col = "blue") +
geom_vline(xintercept = median(credit$V11), col = "red") +
geom_rug(data=credit, aes(x=V11, y=0), sides="b", position="jitter") +
theme_minimal()
```
- **Observación:** Valores **bajos predominantes**, existe una **cola extendida** hacia valores **altos**. Similar a los anteriores.
```{r, fig.width=5, fig.height=3}
ggplot(credit, aes(x = V14)) +
geom_histogram(fill = "orange", color = "black", bins = 20, alpha = 0.7) +
labs(title = "Distribución de V14", x = "V14", y = "Frecuencia") +
geom_vline(xintercept = mean(credit$V14), col = "blue") +
geom_vline(xintercept = median(credit$V14), col = "red") +
geom_rug(data=credit, aes(x=V14, y=0), sides="b", position="jitter") +
theme_minimal()
```
- **Observación:** Valores mayoritariamente **bajos**. Similar a **V2**, pero con una **concentración muy alta** al principio.
```{r, fig.width=5, fig.height=3}
ggplot(credit, aes(x = V15)) +
geom_histogram(fill = "orange", color = "black", bins = 20, alpha = 0.7) +
labs(title = "Distribución de V15", x = "V15", y = "Frecuencia") +
geom_vline(xintercept = mean(credit$V15), col = "blue") +
geom_vline(xintercept = median(credit$V15), col = "red") +
geom_rug(data=credit, aes(x=V15, y=0), sides="b", position="jitter") +
theme_minimal()
```
- **Observación:** Similar a **V3** o **V8**, pero con una **concentración en el rango bajo** mucho más **exagerada** y una **cola extendida muy larga** aunque con **muy poca frecuencia**. Es posible que se traten de **datos atípicos** aunque podría estar relacionado con la **aprobación del crédito**.
## Análisis de cada variable en función del crédito
### Variables Categóricas
```{r, fig.width=5, fig.height=3}
# Análisis de cada variable categórica frente a la aprobación del crédito (V16)
ggplot(data = credit, aes(x = V1, fill = V16)) +
geom_bar() +
labs(y = "Proporción", x = 'V1') + ggtitle('V1 vs V16') +
theme_minimal()
```
Hay una **mayor proporción** de **aprobaciones** en `b`, que en `a`. Se ve una **distribución desigual**, por lo que podríamos pensar que **es más probable que `b` tenga el crédito aprobado**, comparado con `a`.
```{r, fig.width=5, fig.height=3}
ggplot(data = credit, aes(x = V4, fill = V16)) +
geom_bar() +
labs(y = "Proporción", x = 'V4') + ggtitle('V4 vs V16') +
theme_minimal()
```
En este caso, `u` es la que parece estar relacionada con un **mayor porcentaje** de ser **aprobado**, pero a su vez, también con el **mayor porcentaje** de **no** ser **aprobado**. La **categoría `y`** tiene una **predominancia a no ser aprobada**, lo que podría ayudar a predecir.
Por otro lado, `l` tiene muy **poca cantidad de datos**. Podríamos pensar que es **ruido** o un caso muy especial, en el que se aprueba el crédito. **Más adelante**, lo **analizaremos en mayor profundidad** y veremos si los quitamos o no.
```{r, fig.width=5, fig.height=3}
ggplot(data = credit, aes(x = V5, fill = V16)) +
geom_bar() +
labs(y = "Proporción", x = 'V5') + ggtitle('V5 vs V16') +
theme_minimal()
```
En el caso `g`, podemos apreciar una **distribución más homogénea** entre **aprobados** y **no aprobados**. Las demás, son **proporciones más bajas**.
Y al igual que antes, en `gg`, podríamos considerar que son **datos anómalos** o **ruido**. **Debemos analizarlo posteriormente** para ver si los seguimos considerando, o no.
```{r, fig.width=5, fig.height=3}
ggplot(data = credit, aes(x = V6, fill = V16)) +
geom_bar() +
labs(y = "Proporción", x = 'V6') + ggtitle('V6 vs V16') +
theme_minimal()
```
Se ve como la **categoría `c`** es la que **mayor número de no aprobado tiene**, por lo que podría ser de **alto riesgo**, aunque no es el que más tiene en término de porcentaje. Por ejemplo, **`ff`** e **`i`** tienen una **clara tendencia a no ser aprobada**. Por otro lado, el nivel **`cc`** y **`x`** son los que **mayor tasa de aprobado tienen**.
Además, volvemos a encontrarnos con categorías que tienen **pocos datos**, **como `j` y `r`**, en comparación con las demás.
Podríamos pensar que hay **subgrupos de niveles** que podrían ser **relevantes** para nuestra **función objetivo**, pues en general, **V6 muestra diferencias** en la tasa de aprobado **según la categoría**.
```{r, fig.width=5, fig.height=3}
ggplot(data = credit, aes(x = V7, fill = V16)) +
geom_bar() +
labs(y = "Proporción", x = 'V7') + ggtitle('V7 vs V16') +
theme_minimal()
```
Vemos que **`ff`** y **`v`** son de las **categorías** con **mayor probabilidad de no tener el crédito aprobado**, **`h`** es una **categoría bastante favorable a tener el crédito aprobado** y tenemos categorías con **pocos datos**, como `dd`, `j`, `n`, `o` y `z`, que podrían ser **valores atípicos**.
Es así, que **V7 también parece ser una variable que afecta a la probabilidad** de tener o no el aprobado.
```{r, fig.width=5, fig.height=3}
ggplot(data = credit, aes(x = V9, fill = V16)) +
geom_bar() +
labs(y = "Proporción", x = 'V9') + ggtitle('V9 vs V16') +
theme_minimal()
```
La categoría **`f`** es **muy favorable a que no le aprueben el crédito**, mientras que **`t` sí tiene una mayor tasa de aprobado**. Esto, sumado a que tienen una **frecuencia muy parecida**, hace que sea una variable **muy a tener en cuenta a la hora de clasificar**.
En conclusión, **V9 es una variable bastante discriminante**.
```{r, fig.width=5, fig.height=3}
ggplot(data = credit, aes(x = V10, fill = V16)) +
geom_bar() +
labs(y = "Proporción", x = 'V10') + ggtitle('V10 vs V16') +
theme_minimal()
```
En este caso, **`f`** es **más favorable a que no le aprueben el crédito**, mientras que **`t`** **se relaciona con un porcentaje mayor de aprobados**.
**V10 podría ser una variable relevante para predecir el aprobado.**
```{r, fig.width=5, fig.height=3}
ggplot(data = credit, aes(x = V12, fill = V16)) +
geom_bar() +
labs(y = "Proporción", x = 'V12') + ggtitle('V12 vs V16') +
theme_minimal()
```
La diferencia entre ambas categorías **no parece ser muy grande**. De modo que **parece que no hay relación entre ellas**.
```{r, fig.width=5, fig.height=3}
ggplot(data = credit, aes(x = V13, fill = V16)) +
geom_bar() +
labs(y = "Proporción", x = 'V13') + ggtitle('V13 vs V16') +
theme_minimal()
```
La categoría **`g`** es **bastante dominante**, donde **predominan los rechazos aunque con poca fuerza**. Mientras que **`p`** y **`s`** tienen **muy pocos datos**. Podrían tratarse de **valores atípicos**.
Esto hace que **V13 no sea potencialmente una buena variable para discriminar**.
### Variables Numéricas
```{r, fig.width=5, fig.height=3}
ggplot(credit, aes(x= V16, y= V2, fill= V16)) +
geom_boxplot() +
labs(y = "V2", x = 'V16') + ggtitle('V2 vs V16') +
scale_fill_brewer(palette = "Set2")
```
Se aprecia como la **mediana** de los que tuvieron el crédito **rechazado** es **mayor** que la mediana de los que fueron **aprobados**. Pero no parece haber una **correlación fuerte**.
```{r, fig.width=5, fig.height=3}
ggplot(credit, aes(x= V16, y= V3, fill= V16)) +
geom_boxplot() +
labs(y = "V3", x = 'V16') + ggtitle('V3 vs V16') +
scale_fill_brewer(palette = "Set2")
```
La **mediana** de los **aprobados** es **mayor** que la de los **rechazados**. Por tanto, los valores más altos de **V3** podrían tener mayor posibilidad de ser **aprobados**. Los **rechazados** tienden a agruparse en los **valores bajos**. Parece que **V3** tiene cierta capacidad **discriminante**.
```{r, fig.width=5, fig.height=3}
ggplot(credit, aes(x= V16, y= V8, fill= V16)) +
geom_boxplot() +
labs(y = "V8", x = 'V16') + ggtitle('V8 vs V16') +
scale_fill_brewer(palette = "Set2")
```
Al igual que **V3**, se ve como la **mediana** de los **aprobados** es **mayor** que la de los **rechazados**. Por lo que para **valores más altos**, hay **mayor tasa de aprobados**. Y que los **no aprobados**, se concentran en **valores bajos**. Aquí sí que se ve una **gran diferencia** entre ambos, por lo que quizás sería una buena consideración para el modelo.
```{r, fig.width=5, fig.height=3}
ggplot(credit, aes(x= V16, y= V11, fill= V16)) +
geom_boxplot() +
labs(y = "V11", x = 'V16') + ggtitle('V11 vs V16') +
scale_fill_brewer(palette = "Set2")
```
Con **V11**, volvemos a ver una **relación positiva**, y bastante **discriminante**. Para los **valores mayores, se relacionan principalmente con aprobados**, mientras que los **valores más bajos**, se relacionan con el **rechazo**.
```{r, fig.width=5, fig.height=3}
ggplot(credit, aes(x= V16, y= V14, fill= V16)) +
geom_boxplot() +
labs(y = "V14", x = 'V16') + ggtitle('V14 vs V16') +
scale_fill_brewer(palette = "Set2")
```
La **mediana** de los **no aprobados** es **menor**, concentrándose en los **valores más bajos**, y la **mediana** de los **aprobados** es **mayor**, por lo que la **tasa de aprobados** se asocia a **valores mayores** de **V14**.
Existen **valores atípicos**, pues hay casos que se van hasta **2000**. Más adelante nos encargaremos de **analizarlos**.
```{r, fig.width=5, fig.height=3}
ggplot(credit, aes(x= V16, y= V15, fill= V16)) +
geom_boxplot() +
labs(y = "V15", x = 'V16') + ggtitle('V15 vs V16') +
scale_fill_brewer(palette = "Set2")
```
En este último **boxplot** comparando con **V15**, se ve que tenemos **valores atípicos**, que nos hacen ver la gráfica con **poca claridad**. Más adelante, nos encargaremos de **analizar los valores atípicos**, pero por ahora, solo vamos a **escalar la gráfica** con tal de verlo mejor.
```{r, fig.width=5, fig.height=3}
ggplot(credit, aes(x= V16, y= V15, fill= V16)) +
geom_boxplot() +
labs(y = "V15", x = 'V16') + ggtitle('V15 vs V16') +
scale_fill_brewer(palette = "Set2") +
coord_cartesian(ylim=c(0, 2000))
```
Podemos ver una **fuerte relación** entre **V15** y la **variable objetivo**. Parece ser que es una **variable altamente discriminante**, y que existe una **correlación positiva**.
## Análisis de Outliers
Con las visualizaciones anteriores, hemos visto que hay datos
considerados atípicos, y que nos encargaríamos de analizarlos. Es
importante tratarlos de cara a los modelos que vayamos a entrenar, pues
**podría influir de mala manera en los resultados**. Es por ello, que los trataremos
con el conjunto de train.
Vamos a pasar las variables numéricas a formato largo, con tal de poder
generar los boxplots para todas, y así visualizarlas de manera conjunta
y detectar valores atípicos.
```{r}
# Transformar el dataset al formato largo
credit_melt <- melt(credit.Datos.Train, measure.vars = which(numeric_columns))
head(credit_melt)
```
```{r, fig.width=5, fig.height=3}
# Boxplots de todas las variables numéricas
ggplot(credit_melt, aes(x = variable, y = value)) +
geom_boxplot(fill = "skyblue", outlier.color = "red", outlier.shape = 16) +
labs(
title = "Boxplots de Variables Numéricas",
x = "Variables",
y = "Valores"
) +
theme_minimal()
```
Como podemos ver, **V15** es la **variable** que **más se dispara con diferencia**.
### Boxplots desgregados por Clase (V16)
Si ahora los visualizamos desgregados por la variable objetivo,
podríamos ver cómo los outliers podrían afectar a esta.
```{r, fig.width=5, fig.height=3}
ggplot(credit_melt, aes(x = variable, y = value, fill = V16)) +
geom_boxplot(outlier.color = "red", outlier.shape = 16) +
labs(
title = "Boxplots de Variables Numéricas por Clase",
x = "Variables",
y = "Valores",
fill = "Clase"
) +
theme_minimal()
```
Aquí tambien hay un **número significativo de outliers en V15**,concentrándose en **valores extremos muy altos**.
### Criterio de Turkey
La manera más fácil de tratar outliers es con el **Criterio de Turkey**. Consiste en eliminar los **valores atípicos**, utilizando el **rango intercuartílico (IQR)** para detectar los **límites superior e inferior**. Los que queden fuera de esos límites, se consideran **outliers**.
```{r}
# Función para detectar outliers
detect_outliers <- function(x) {
Q1 <- quantile(x, 0.25, na.rm = TRUE)
Q3 <- quantile(x, 0.75, na.rm = TRUE)
IQR <- Q3 - Q1
lower_bound <- Q1 - 1.5 * IQR
upper_bound <- Q3 + 1.5 * IQR
return(x < lower_bound | x > upper_bound)
}
# Detectar outliers por variable
outliers <- lapply(credit.Datos.Train[numeric_columns], detect_outliers)
# Contar outliers por variable
sapply(outliers, sum)
total_outliers <- sum(sapply(outliers, sum))
total_outliers
```
Aparecen demasiados valores considerados outliers.
### Distancias de Mahalanobis
Vamos a probar con otro criterio, pero esta vez **tiene en cuenta outliers multivariados**. O sea, se consideran las **relaciones entre las distintas variables** y nos ayuda a detectar **patrones anómalos** al patrón general de los datos.
```{r, fig.width=5, fig.height=3}
# Cálculo y visualización de distancias de Mahalanobis
#Calcular vector de medias y matriz de covarianza
mean_vector <- colMeans(credit.Datos.Train[, numeric_columns], na.rm = TRUE)
cov_matrix <- cov(credit.Datos.Train[, numeric_columns], use = "complete.obs")
# Calcular distancias de Mahalanobis
mahalanobis_distances <- mahalanobis(credit.Datos.Train[, numeric_columns], center = mean_vector, cov = cov_matrix)
# Umbral para identificar outliers (97.5% de confianza)
threshold <- qchisq(0.975, df = ncol(credit.Datos.Train[, numeric_columns]))
# Identificar outliers
outliers <- which(mahalanobis_distances > threshold)
plot(mahalanobis_distances,
main = "Distancias de Mahalanobis",
xlab = "Índice de Observación",
ylab = "Distancia de Mahalanobis",
pch = 19, col = "blue")
abline(h = threshold, col = "red", lty = 2) # Línea roja para el umbral
# outliers totales
num_outliers <- length(outliers)
cat("Número de outliers identificados:", num_outliers, "\n")
```
Comparado con el criterio de Turkey, hay muchos menos outliers.
### Acciones a tomar ante los outliers
Como no tenemos ningún contexto de lo que es cada variable, pues están codificadas, y no tenemos a ningún experto que nos pudiera ayudar, vamos a optar por **quitar los outliers**. Además, vamos a emplear el **criterio de las distancias de Mahalanobis**, pues con el **criterio de Turkey**, se elimina una **gran cantidad de datos**, y tampoco nos podemos permitir eso, al ser un dataset bastante **"pequeño"** ya de por sí. Por no decir que es **más robusto** un **análisis multivariado** que tiene en cuenta las **relaciones entre las variables**.
```{r}
# Verificar el tamaño del dataset antes de eliminar los outliers
cat("Número de filas antes de eliminar outliers:", nrow(credit.Datos.Train), "\n")
# Eliminar los outliers del dataset
credit.Datos.Train <- credit.Datos.Train[-outliers, ]
# Verificar el tamaño del dataset después de eliminar los outliers
cat("Número de filas después de eliminar outliers:", nrow(credit.Datos.Train), "\n")
```
### Revisualizar los datos después de quitar los outliers
```{r graficos-grid2, fig.width=10, fig.height=12, echo=FALSE, warning=FALSE}
# Crear lista de gráficos para variables numéricas
numeric_plots <- lapply(numeric_columns2, function(col) {
ggplot(credit.Datos.Train, aes_string(y = col)) +
geom_boxplot(fill = "orange", color = "black", outlier.color = "red") +
labs(title = paste("Boxplot de", col), y = col, x = "") +
theme_minimal()
})
# Mostrar gráficos numéricos en un grid
grid.arrange(grobs = numeric_plots, ncol = 2, top = "Variables Numéricas")
```
Los **boxplots** han cambiado con respecto a los que vimos anteriormente. Pero se observa que aún así, en **V15 sigue teniendo una gran cantidad de valores extremadamente elevados**. Como hemos empleado un **enfoque multivariado** para eliminar los **outliers**, esto sugiere que esos **valores tan extremos no son inconsistentes con el resto de variables del dataset**. Esto podría indicar que **V15** refleja algún tipo de **métrica económica**, o algo relacionado con el **dinero** de las personas, lo que justificaría la presencia de valores altos en algunos casos.
No obstante, más adelante, nos encargaremos de **normalizar los datos**, con tal de que esta diferencia de escala no afecte a los modelos. Si tuviéramos **contexto** de esta variable, sería más fácil decidir si recortar de una manera más agresiva o dejarla así, por tener un significado útil. Pero **nos fiaremos del enfoque multivariado**.
## Comprobar distribución
Es interesante comprobar las **distribuciones** que siguen las variables, **a la hora de aplicar transformaciones adicionales**, pues **hay modelos que necesitan tener los datos normalizados** o que sigan una cierta forma. Para ello, vamos a realizar los **Q-Q plots** correspondientes a las distribuciones más comunes, como la **normal**, **binomial**, **exponencial**, **geométrica** o **poisson**.
### Distribución Normal
Las variables numericas, a simple vista con las gráficas anteriores,
no parecen seguir una distribución normal. Sino, una geometrica o exponencial.
De todos modos, vamos a mirar si las variables se adaptan a una
distribución normal.
```{r graficas Q-Q, fig.width=14, fig.height=10}
p1 = ggplot(data=credit.Datos.Train, aes(sample=credit.Datos.Train[,2])) +
ggtitle("QQ plot V2") +
geom_qq() +
stat_qq_line() +
xlab("Distribución teórica") + ylab("Distribución muestral")
p2 = ggplot(data=credit.Datos.Train, aes(sample=credit.Datos.Train[,3])) +
ggtitle("QQ plot V3") +
geom_qq() +
stat_qq_line() +
xlab("Distribución teórica") + ylab("Distribución muestral")
p3 = ggplot(data=credit.Datos.Train, aes(sample=credit.Datos.Train[,8])) +
ggtitle("QQ plot V8") +
geom_qq() +
stat_qq_line() +
xlab("Distribución teórica") + ylab("Distribución muestral")
p4 = ggplot(data=credit.Datos.Train, aes(sample=credit.Datos.Train[,11])) +
ggtitle("QQ plot V11") +
geom_qq() +
stat_qq_line() +
xlab("Distribución teórica") + ylab("Distribución muestral")
p5 = ggplot(data=credit.Datos.Train, aes(sample=credit.Datos.Train[,14])) +
ggtitle("QQ plot V14") +
geom_qq() +
stat_qq_line() +
xlab("Distribución teórica") + ylab("Distribución muestral")
p6 = ggplot(data=credit.Datos.Train, aes(sample=credit.Datos.Train[,15])) +
ggtitle("QQ plot V15") +
geom_qq() +
stat_qq_line() +
xlab("Distribución teórica") + ylab("Distribución muestral")
#Organizando los gráficos en un solo lienzo
grid.arrange(p1, p2, p3, p4, p5, p6, nrow=2)
```
En las QQ plots ajustadas a la distribución normal, se puede observar que
**ninguna de las variables sigue un comportamiento cercano a la normalidad**.
Además, las variables muestran colas alargadas (asimetría positiva) en
los valores altos.
### Distribución Binomial
```{r graficas Q-Q Binomial, fig.width=14, fig.height=10}
# Establecer los parámetros para cada variable
# Usamos como número de ensayos (n) la máxima observación + 1, por simplicidad
n_v2 <- max(credit.Datos.Train[, 2]) + 1
n_v3 <- max(credit.Datos.Train[, 3]) + 1
n_v8 <- max(credit.Datos.Train[, 8]) + 1
n_v11 <- max(credit.Datos.Train[, 11]) + 1
n_v14 <- max(credit.Datos.Train[, 14]) + 1
n_v15 <- max(credit.Datos.Train[, 15]) + 1
# Probabilidad de éxito (p) como media / n
p_binom_v2 <- mean(credit.Datos.Train[, 2]) / n_v2
p_binom_v3 <- mean(credit.Datos.Train[, 3]) / n_v3
p_binom_v8 <- mean(credit.Datos.Train[, 8]) / n_v8
p_binom_v11 <- mean(credit.Datos.Train[, 11]) / n_v11
p_binom_v14 <- mean(credit.Datos.Train[, 14]) / n_v14
p_binom_v15 <- mean(credit.Datos.Train[, 15]) / n_v15
# Crear gráficos Q-Q para cada variable
p1_binomial <- ggplot(data = credit.Datos.Train, aes(sample = credit.Datos.Train[, 2])) +
stat_qq(distribution = stats::qbinom, dparams = list(size = n_v2, prob = p_binom_v2)) +
stat_qq_line(distribution = stats::qbinom, dparams = list(size = n_v2, prob = p_binom_v2)) +
ggtitle("QQ plot - Distribución Binomial (V2)") +
xlab("Cuantiles teóricos") + ylab("Cuantiles observados") +
theme_minimal()
p2_binomial <- ggplot(data = credit.Datos.Train, aes(sample = credit.Datos.Train[, 3])) +
stat_qq(distribution = stats::qbinom, dparams = list(size = n_v3, prob = p_binom_v3)) +
stat_qq_line(distribution = stats::qbinom, dparams = list(size = n_v3, prob = p_binom_v3)) +
ggtitle("QQ plot - Distribución Binomial (V3)") +
xlab("Cuantiles teóricos") + ylab("Cuantiles observados") +
theme_minimal()
p3_binomial <- ggplot(data = credit.Datos.Train, aes(sample = credit.Datos.Train[, 8])) +
stat_qq(distribution = stats::qbinom, dparams = list(size = n_v8, prob = p_binom_v8)) +
stat_qq_line(distribution = stats::qbinom, dparams = list(size = n_v8, prob = p_binom_v8)) +
ggtitle("QQ plot - Distribución Binomial (V8)") +
xlab("Cuantiles teóricos") + ylab("Cuantiles observados") +
theme_minimal()
p4_binomial <- ggplot(data = credit.Datos.Train, aes(sample = credit.Datos.Train[, 11])) +
stat_qq(distribution = stats::qbinom, dparams = list(size = n_v11, prob = p_binom_v11)) +
stat_qq_line(distribution = stats::qbinom, dparams = list(size = n_v11, prob = p_binom_v11)) +
ggtitle("QQ plot - Distribución Binomial (V11)") +
xlab("Cuantiles teóricos") + ylab("Cuantiles observados") +
theme_minimal()
p5_binomial <- ggplot(data = credit.Datos.Train, aes(sample = credit.Datos.Train[, 14])) +
stat_qq(distribution = stats::qbinom, dparams = list(size = n_v14, prob = p_binom_v14)) +
stat_qq_line(distribution = stats::qbinom, dparams = list(size = n_v14, prob = p_binom_v14)) +
ggtitle("QQ plot - Distribución Binomial (V14)") +
xlab("Cuantiles teóricos") + ylab("Cuantiles observados") +
theme_minimal()
p6_binomial <- ggplot(data = credit.Datos.Train, aes(sample = credit.Datos.Train[, 15])) +
stat_qq(distribution = stats::qbinom, dparams = list(size = n_v15, prob = p_binom_v15)) +
stat_qq_line(distribution = stats::qbinom, dparams = list(size = n_v15, prob = p_binom_v15)) +
ggtitle("QQ plot - Distribución Binomial (V15)") +
xlab("Cuantiles teóricos") + ylab("Cuantiles observados") +
theme_minimal()
# Organizar gráficos en un grid
grid.arrange(p1_binomial, p2_binomial, p3_binomial, p4_binomial, p5_binomial, p6_binomial, nrow = 2)
```
Observando las gráficas, podemos ver que **tampoco se ajusta a una distribución binomial**. Especialmente en variables como V3 y V11, donde los valores esperados no coinciden con los observados.
### Distribución Exponencial
```{r graficas Q-Q Exponencial, fig.width=14, fig.height=10}
# Calcular el parámetro lambda (rate) para cada variable
lambda_exp_v2 <- 1 / mean(credit.Datos.Train[, 2])
lambda_exp_v3 <- 1 / mean(credit.Datos.Train[, 3])
lambda_exp_v8 <- 1 / mean(credit.Datos.Train[, 8])
lambda_exp_v11 <- 1 / mean(credit.Datos.Train[, 11])
lambda_exp_v14 <- 1 / mean(credit.Datos.Train[, 14])
lambda_exp_v15 <- 1 / mean(credit.Datos.Train[, 15])
# Crear gráficos Q-Q para cada variable
p1_exponential <- ggplot(data = credit.Datos.Train, aes(sample = credit.Datos.Train[, 2])) +
stat_qq(distribution = stats::qexp, dparams = list(rate = lambda_exp_v2)) +
stat_qq_line(distribution = stats::qexp, dparams = list(rate = lambda_exp_v2)) +
ggtitle("QQ plot - Distribución Exponencial (V2)") +
xlab("Cuantiles teóricos") + ylab("Cuantiles observados") +
theme_minimal()
p2_exponential <- ggplot(data = credit.Datos.Train, aes(sample = credit.Datos.Train[, 3])) +
stat_qq(distribution = stats::qexp, dparams = list(rate = lambda_exp_v3)) +
stat_qq_line(distribution = stats::qexp, dparams = list(rate = lambda_exp_v3)) +
ggtitle("QQ plot - Distribución Exponencial (V3)") +
xlab("Cuantiles teóricos") + ylab("Cuantiles observados") +
theme_minimal()
p3_exponential <- ggplot(data = credit.Datos.Train, aes(sample = credit.Datos.Train[, 8])) +
stat_qq(distribution = stats::qexp, dparams = list(rate = lambda_exp_v8)) +
stat_qq_line(distribution = stats::qexp, dparams = list(rate = lambda_exp_v8)) +
ggtitle("QQ plot - Distribución Exponencial (V8)") +
xlab("Cuantiles teóricos") + ylab("Cuantiles observados") +
theme_minimal()
p4_exponential <- ggplot(data = credit.Datos.Train, aes(sample = credit.Datos.Train[, 11])) +
stat_qq(distribution = stats::qexp, dparams = list(rate = lambda_exp_v11)) +
stat_qq_line(distribution = stats::qexp, dparams = list(rate = lambda_exp_v11)) +
ggtitle("QQ plot - Distribución Exponencial (V11)") +
xlab("Cuantiles teóricos") + ylab("Cuantiles observados") +
theme_minimal()
p5_exponential <- ggplot(data = credit.Datos.Train, aes(sample = credit.Datos.Train[, 14])) +
stat_qq(distribution = stats::qexp, dparams = list(rate = lambda_exp_v14)) +
stat_qq_line(distribution = stats::qexp, dparams = list(rate = lambda_exp_v14)) +
ggtitle("QQ plot - Distribución Exponencial (V14)") +
xlab("Cuantiles teóricos") + ylab("Cuantiles observados") +
theme_minimal()
p6_exponential <- ggplot(data = credit.Datos.Train, aes(sample = credit.Datos.Train[, 15])) +
stat_qq(distribution = stats::qexp, dparams = list(rate = lambda_exp_v15)) +
stat_qq_line(distribution = stats::qexp, dparams = list(rate = lambda_exp_v15)) +
ggtitle("QQ plot - Distribución Exponencial (V15)") +
xlab("Cuantiles teóricos") + ylab("Cuantiles observados") +
theme_minimal()
# Organizar gráficos en un grid
grid.arrange(p1_exponential, p2_exponential, p3_exponential,
p4_exponential, p5_exponential, p6_exponential, nrow = 2)
```
Viedno estas gráficas, la **única que se ajusta razonadamente a la distribución exponencial es la V8**, especialmente en los valores más bajos, mientras que
las demás variables, como **V2** y **V15**, **presentan grandes desviaciones en las colas**.
Esto indica que V8 podría modelar procesos decayentes, como tiempos.
### Distribución Geométrica
```{r graficas Q-Q Geométrica, fig.width=14, fig.height=10}
# Calcular el parámetro p para cada variable
p_geom_v2 <- 1 / mean(credit.Datos.Train[, 2])
p_geom_v3 <- 1 / mean(credit.Datos.Train[, 3])
p_geom_v8 <- 1 / mean(credit.Datos.Train[, 8])
p_geom_v11 <- 1 / mean(credit.Datos.Train[, 11])
p_geom_v14 <- 1 / mean(credit.Datos.Train[, 14])
p_geom_v15 <- 1 / mean(credit.Datos.Train[, 15])
# Crear gráficos Q-Q para cada variable
p1_geometric <- ggplot(data = credit.Datos.Train, aes(sample = credit.Datos.Train[, 2])) +
stat_qq(distribution = stats::qgeom, dparams = list(prob = p_geom_v2)) +
stat_qq_line(distribution = stats::qgeom, dparams = list(prob = p_geom_v2)) +
ggtitle("QQ plot - Distribución Geométrica (V2)") +
xlab("Cuantiles teóricos") + ylab("Cuantiles observados") +
theme_minimal()
p2_geometric <- ggplot(data = credit.Datos.Train, aes(sample = credit.Datos.Train[, 3])) +
stat_qq(distribution = stats::qgeom, dparams = list(prob = p_geom_v3)) +
stat_qq_line(distribution = stats::qgeom, dparams = list(prob = p_geom_v3)) +
ggtitle("QQ plot - Distribución Geométrica (V3)") +
xlab("Cuantiles teóricos") + ylab("Cuantiles observados") +
theme_minimal()
p3_geometric <- ggplot(data = credit.Datos.Train, aes(sample = credit.Datos.Train[, 8])) +
stat_qq(distribution = stats::qgeom, dparams = list(prob = p_geom_v8)) +
stat_qq_line(distribution = stats::qgeom, dparams = list(prob = p_geom_v8)) +
ggtitle("QQ plot - Distribución Geométrica (V8)") +
xlab("Cuantiles teóricos") + ylab("Cuantiles observados") +
theme_minimal()
p4_geometric <- ggplot(data = credit.Datos.Train, aes(sample = credit.Datos.Train[, 11])) +
stat_qq(distribution = stats::qgeom, dparams = list(prob = p_geom_v11)) +
stat_qq_line(distribution = stats::qgeom, dparams = list(prob = p_geom_v11)) +
ggtitle("QQ plot - Distribución Geométrica (V11)") +
xlab("Cuantiles teóricos") + ylab("Cuantiles observados") +
theme_minimal()
p5_geometric <- ggplot(data = credit.Datos.Train, aes(sample = credit.Datos.Train[, 14])) +
stat_qq(distribution = stats::qgeom, dparams = list(prob = p_geom_v14)) +
stat_qq_line(distribution = stats::qgeom, dparams = list(prob = p_geom_v14)) +
ggtitle("QQ plot - Distribución Geométrica (V14)") +
xlab("Cuantiles teóricos") + ylab("Cuantiles observados") +
theme_minimal()
p6_geometric <- ggplot(data = credit.Datos.Train, aes(sample = credit.Datos.Train[, 15])) +
stat_qq(distribution = stats::qgeom, dparams = list(prob = p_geom_v15)) +
stat_qq_line(distribution = stats::qgeom, dparams = list(prob = p_geom_v15)) +
ggtitle("QQ plot - Distribución Geométrica (V15)") +
xlab("Cuantiles teóricos") + ylab("Cuantiles observados") +
theme_minimal()
# Organizar gráficos en un grid
grid.arrange(p1_geometric, p2_geometric, p3_geometric,
p4_geometric, p5_geometric, p6_geometric, nrow = 2)
```
Una vez más no parece que ninguna se ajuste a una distribución geométrica tampoco.
### Distribución Poisson
```{r graficas Q-Q Poisson, fig.width=14, fig.height=10}
# Calcular el parámetro lambda (la media de cada variable)
lambda_pois_v2 <- mean(credit.Datos.Train[, 2])
lambda_pois_v3 <- mean(credit.Datos.Train[, 3])
lambda_pois_v8 <- mean(credit.Datos.Train[, 8])
lambda_pois_v11 <- mean(credit.Datos.Train[, 11])
lambda_pois_v14 <- mean(credit.Datos.Train[, 14])
lambda_pois_v15 <- mean(credit.Datos.Train[, 15])
# Crear gráficos Q-Q para cada variable
p1_poisson <- ggplot(data = credit.Datos.Train, aes(sample = credit.Datos.Train[, 2])) +
stat_qq(distribution = stats::qpois, dparams = list(lambda = lambda_pois_v2)) +
stat_qq_line(distribution = stats::qpois, dparams = list(lambda = lambda_pois_v2)) +
ggtitle("QQ plot - Distribución Poisson (V2)") +
xlab("Cuantiles teóricos") + ylab("Cuantiles observados") +
theme_minimal()
p2_poisson <- ggplot(data = credit.Datos.Train, aes(sample = credit.Datos.Train[, 3])) +
stat_qq(distribution = stats::qpois, dparams = list(lambda = lambda_pois_v3)) +
stat_qq_line(distribution = stats::qpois, dparams = list(lambda = lambda_pois_v3)) +
ggtitle("QQ plot - Distribución Poisson (V3)") +
xlab("Cuantiles teóricos") + ylab("Cuantiles observados") +
theme_minimal()
p3_poisson <- ggplot(data = credit.Datos.Train, aes(sample = credit.Datos.Train[, 8])) +
stat_qq(distribution = stats::qpois, dparams = list(lambda = lambda_pois_v8)) +
stat_qq_line(distribution = stats::qpois, dparams = list(lambda = lambda_pois_v8)) +
ggtitle("QQ plot - Distribución Poisson (V8)") +
xlab("Cuantiles teóricos") + ylab("Cuantiles observados") +
theme_minimal()
p4_poisson <- ggplot(data = credit.Datos.Train, aes(sample = credit.Datos.Train[, 11])) +
stat_qq(distribution = stats::qpois, dparams = list(lambda = lambda_pois_v11)) +
stat_qq_line(distribution = stats::qpois, dparams = list(lambda = lambda_pois_v11)) +
ggtitle("QQ plot - Distribución Poisson (V11)") +
xlab("Cuantiles teóricos") + ylab("Cuantiles observados") +
theme_minimal()
p5_poisson <- ggplot(data = credit.Datos.Train, aes(sample = credit.Datos.Train[, 14])) +
stat_qq(distribution = stats::qpois, dparams = list(lambda = lambda_pois_v14)) +
stat_qq_line(distribution = stats::qpois, dparams = list(lambda = lambda_pois_v14)) +
ggtitle("QQ plot - Distribución Poisson (V14)") +
xlab("Cuantiles teóricos") + ylab("Cuantiles observados") +