En esta sección, se realiza la carga inicial de los datos desde múltiples archivos CSV y se lleva a cabo un proceso de limpieza y transformación para estandarizar los nombres de las columnas y convertir las variables de años y víctimas en formatos numéricos utilizables para el análisis.
Code
# Primero verificamos la ruta de trabajo del presente archivogetwd()# Ubicamos la ruta de trabajo de los archivos csv a trabajarsetwd("C:/Users/DELL LATITUDE 3500/Documents/Libros/R/CDV - CD/archive")# Creamos una variable por cada archivo csv descomprimidodatos_1 <-read.csv("5_to_14_victim_count.csv", stringsAsFactors =FALSE)datos_2 <-read.csv("15_to_30_victim_count.csv", stringsAsFactors =FALSE)datos_3 <-read.csv("Highest_victim_count.csv", stringsAsFactors =FALSE)datos_4 <-read.csv("Lessthan_5_victim_count.csv", stringsAsFactors =FALSE)# Juntamos todos los datos en una única tablaserial_killers_datos <-rbind(datos_1, datos_2, datos_3, datos_4)# En este caso podemos usar la función "rbin" porque cada tabla individual contaba con el mismo número, nombre y orden de columnas# Limpiamos el formato de los nombres de las columnas a un formato más adecuadonames(serial_killers_datos) serial_killers_datos <- serial_killers_datos %>% janitor::clean_names() # Verificamos las dimensiones y vemos la clase que le asignó a cada columnadim(serial_killers_datos)apply(serial_killers_datos,2, class)# Hay que hacer tres modificaciones de clases de "charater" a "numeric"# Realizamos las transformacionesdf_transformacion <- serial_killers_datos %>%# Primero la transformación para los años mutate(rango_limpio =str_replace_all(years_active, "[^0-9to\\s]", "")) %>%mutate(rango_limpio =str_squish(rango_limpio))%>%mutate(año_inicio =as.numeric(str_extract(rango_limpio, "\\d{4}"))) %>%mutate(año_fin =case_when(str_detect(rango_limpio, " to | \\- ") ~as.numeric(str_extract(rango_limpio, "\\d{4}$")), TRUE~ año_inicio)) %>%# Ahora la transformación para los "proven_victims"mutate(rango_limpio_kills =str_replace_all(proven_victims, "[^0-9–+-]", ""),rango_limpio_kills =str_squish(rango_limpio_kills),victimas_min =as.numeric(str_extract(rango_limpio_kills, "^\\d+")),victimas_max =case_when(str_detect(rango_limpio_kills, "[–-]") ~ { segundo_num_str <-str_split(rango_limpio_kills, "[–-]", simplify =TRUE)[,2]as.numeric(str_remove(segundo_num_str, "\\+")) },str_detect(rango_limpio_kills, "\\d+\\+$") ~as.numeric(str_remove(rango_limpio, "\\+")),str_detect(rango_limpio_kills, "^\\d+$") ~ victimas_min,TRUE~NA_real_ )) %>%# Ahora la transformación para los "possible_victims"mutate(rango_limpio_p =str_replace_all(possible_victims, "[^0-9–+-]", ""),rango_limpio_p =str_squish(rango_limpio_p),p_victimas_min =as.numeric(str_extract(rango_limpio_p, "^\\d+")),p_victimas_max =case_when(str_detect(rango_limpio_p, "[–-]") ~ { tercero_num_str <-str_split(rango_limpio_p, "[–-]", simplify =TRUE)[,2]as.numeric(str_remove(tercero_num_str, "\\+")) },str_detect(rango_limpio_p, "\\d+\\+$") ~as.numeric(str_remove(rango_limpio_p, "\\+")),str_detect(rango_limpio_p, "^\\d+$") ~ p_victimas_min,TRUE~NA_real_ ))# Esta extensa transformación fue resultado de interacción de códigos propios corregidos por Gemini iteradamente.# Selecciono los datos que quiero en la tabladf_transformacion <- df_transformacion %>% dplyr::select(name, country, año_inicio, año_fin,victimas_min, victimas_max, p_victimas_min, p_victimas_max, notes)# Ahora, jugando un poco con los datos, queremos sacar el promedio de las columnas por cada filadf_con_promedios <- df_transformacion %>%rowwise() %>%mutate(promedio_victimas =mean(c_across(c(victimas_min, victimas_max)), na.rm =TRUE) ) %>%mutate(promedio_victimas_estimadas =mean(c_across(c(p_victimas_min, p_victimas_max)), na.rm =TRUE) )# La función "rowwise" fue recomendada por Gemini# Organizamos la df resultantedf_serial_killer_final <- df_con_promedios %>% dplyr::select(name, country, año_inicio, año_fin, promedio_victimas, promedio_victimas_estimadas, notes)
Esta fue la parte más complicada de todo el trabajo, sinceramente después de pasar horas en la limpieza de los datos no me quedaba creatividad para el resto del proyecto.
2. Valores Estadísticos y Tabla Resumen
Para comprender las características principales de las variables numéricas en el conjunto de datos, se presentan medidas de tendencia central, dispersión y rango. Para un análisis más específico, se presenta una tabla con el promedio de víctimas estimadas y el número total de asesinos por cada país.
Promedio de Víctimas Estimadas por País
Número de víctimas estimadas promedio por asesino serial, agrupado por país de actividad.
País
Promedio Víctimas Estimadas
Mediana Víctimas Estimadas
N° Asesinos
Colombia Peru Ecuador
300.00
300.00
1
Colombia Ecuador Venezuela
236.00
236.00
1
Colombia Ecuador Brazil (alleged)
180.00
180.00
1
France Germany (suspected) Switzerland (suspected)
150.00
150.00
1
Pakistan
100.00
100.00
2
German Empire Germany
79.00
79.00
1
Soviet Union Ukraine
71.00
71.00
2
Germany
56.33
42.00
3
Italy
50.80
16.00
6
Brazil
50.20
42.00
8
Spain France (claimed) Italy (claimed)
48.00
48.00
1
Mexico
47.50
34.50
4
Swaziland
45.00
45.00
1
Indonesia
44.50
44.50
3
Bangladesh
43.00
43.00
2
Soviet Union
37.33
33.00
13
Morocco
36.00
36.00
1
Kingdom of Romania Yugoslavia Hungary (alleged)
35.00
35.00
1
China
33.36
25.00
9
Ottoman Empire Iraq Iran
33.00
33.00
1
Egypt
32.00
32.00
1
India
30.67
25.00
10
United States
30.10
20.00
92
Canada
29.50
29.50
5
Latvia
28.50
28.50
2
Russia
28.29
16.50
21
Greece
27.00
27.00
1
South Africa
26.62
18.00
19
Soviet Union Russia
26.33
20.00
4
Colombia
26.25
22.50
4
Romania
26.00
26.00
1
South Korea
26.00
26.00
4
Poland
25.50
25.50
2
Peru
25.00
25.00
1
United States Canada
25.00
25.00
1
West Germany
25.00
25.00
2
Austria-Hungary
24.00
24.00
1
Ecuador
23.00
23.00
1
Soviet Union Russia Tajikistan
22.00
22.00
1
Turkey
22.00
22.00
4
United States Portuguese Angola
22.00
22.00
1
Australia
21.50
21.50
5
Iran
21.00
20.00
3
Afghanistan
20.00
20.00
1
East Germany Germany France Spain Czech Republic (suspected) Italy (suspected)
19.00
19.00
1
France Belgium
19.00
19.00
1
Ukraine
19.00
19.00
2
Austria
18.00
18.00
1
Canada United States
18.00
18.00
1
United Kingdom Ireland (suspected) West Germany (suspected) Netherlands (suspected) France (suspected)
18.00
18.00
1
United States Mexico
18.00
18.00
1
France
17.00
18.50
6
Allied-occupied Germany West Germany
16.00
16.00
1
Japan
16.00
16.00
4
Spain
16.00
16.00
3
Austria United States Czechoslovakia
15.00
15.00
1
Costa Rica
15.00
15.00
2
Denmark
15.00
15.00
1
United Kingdom
14.75
12.75
12
Argentina
14.00
14.00
3
Belgium
14.00
14.00
2
Thailand Nepal India Malaysia
13.00
13.00
1
Belarus
12.00
12.00
1
Netherlands
12.00
12.00
1
Switzerland France United States Yugoslavia (suspected) Italy (suspected)