#!/usr/bin/env python # coding: utf-8 # # Preparació de dades # # # Preparació de dades per a [Innovation and Human Rights](https://ihr.world/ca/projecte-sumarissims). # # En aquest notebook, convertim les dades originals a formats que es poden treballar mès fàcilment a Python, i anem mostrant petites anàlisis. # In[1]: import pandas as pd import numpy as np import plydata as ply import datetime import yaml from functools import lru_cache ply.options.modify_input_data = True # ### Pas 1: llegir arxiu # In[2]: original = pd.read_csv("data/input/20171101_actualitzat_llistat_Llei_11_2017.csv",delimiter=";",encoding="latin-1") # ### Un primer cop d'ull a les dades # In[3]: # sexe "--" marca persones jurídiques original.query("sexe != '--'").head() # ### Pas 2: Canviar noms de columnes a identificadors permesos en *Python* # In[4]: original >> ply.rename( {'afusellades': 'afusellades', 'any_inicial': 'any inicial', 'any_resol': 'any aprovació sen o altra resol', 'ca_naix': 'Comunitat autònoma naixement', 'ca_res': 'Comunitat autònoma residència', 'codi': 'Codi', 'cognoms': 'cognoms', 'cognoms_nom': 'cognoms nom', 'com_naix': 'Comarca naixement', 'com_res': 'Comarca residència', 'correccio': 'data correccio registre', 'descr': 'autoria i data de la descripció', 'edat': 'edat', 'indult': 'commutació/indult(demanat)', 'mun_naix': 'Municipi naixement', 'mun_res': 'Municipi residència', 'nom': 'nom', 'num_causa': 'num causa', 'pais_naix': 'País naixement', 'pais_res': 'País residència', 'ped_naix': 'Pedanies/Agregats naixement', 'ped_res': 'Pedanies/Agregats residencia', 'pena': 'pena', 'proc_1': 'Tipus procediment 1', 'proc_2': 'Tipus procediment 2', 'prov_naix': 'Província naixement', 'prov_res': 'Província residència', 'ref_arxiu': 'ref num arxiu', 'genere': 'sexe'} ) pass # ### Pas 3: Canviar el format dels anys a data per automatitzar el càlcul dels eixos # # # In[5]: # l'ús de lru_cache fa tot més ràpid, perquè cada any només ha de ser convertit a data una sola vegada @lru_cache(maxsize=100) def pd_year(n: float) : try : return pd.date_range(start=datetime.datetime(int(n),1,1),end=datetime.datetime(int(n),12,31),freq="Y")[0] except (TypeError,ValueError,OverflowError) : return n original["any_inicial"] = original["any_inicial"].apply(pd_year) original["any_resol"] = original["any_resol"].apply(pd_year) # ### Primera anàlisi: els sumaríssims de més durada # In[6]: dura = original.loc[:,["cognoms_nom","any_inicial","any_resol","genere","pena","pais_naix"]] dura["dura"] = dura["any_resol"] - dura["any_inicial"] dura.sort_values(["dura"],ascending=False).iloc[:5] # ### Pas 4: Categoritzar penes # # Aquestes categories Es deriven de l’[*Anexo de la Circular de Creación de las Comisiones de Examen de Penas* del any 1940](https://www.boe.es/datos/pdfs/BOE//1940/026/A00662-00665.pdf). # # En alguns casos, les dades publicades són ambigües - per exemple quan la pena és de *"Sobreseïment provisional, tres mesos d'arrest major i llibertat"*. En aquests casos, categoritzem com la pena més greu que es va imposar (*"tres mesos"*). Si queden dubtes, la categoria es "altres" - per exemple amb *"Pena de multa, remissió o a disposició d'altres autoritats"*. # # Cal tenir en compte també que el “sobreseïment” es podia produir també quan la persona havia mort durant la seva reclusió mentre esperava judici o en altres circumstàncies. # # La relació entre les penes que consten a la base de dades original (etiquetes) i les categories analitzades està documentada a l'arxiu [categories.yml](https://github.com/martinvirtel/sumarissims-dades/blob/master/work/data/input/categories.yml). # # | categoria | descripció | | # | ----------| ----------- | --- | # |mort |pena de mort || # |30a+ |30 anys i un dia a perpètua|| # |20-30a |20 anys i un dia a 30 anys |Reclusión Mayor| # |12-20a |12 anys i un día a 20 anys|Menor| # |6-12a |6 anys i un dia a 12 anys |Prisión Mayor| # |6m-6a |6 mesos i un dia a 6 anys |Menor| # |<6m |fins 6 mesos || # |sob |sobreseïment || # |lib |sin pena || # |alt |altres || # # # In[7]: penes_cat = yaml.load(open("data/input/categories.yml")) ord_categories = { a[1]["nom"] : "%02d" % a[0] for a in enumerate(penes_cat["categories"]) } categories_penes={ a["pena"] : "%s %s" % (ord_categories[a["categoria"]],a["categoria"]) for a in penes_cat["etiquetes"] } original["pena_cat"] = original["pena"].apply( lambda a: categories_penes.get(a,None)) # ### Primera anàlisi: relació entre penes imposades i gènere # # # Entre els homes, el grup més gran és el de condemnat a 12 - 20 anys (30.0%). Entre les dones, són les que queden en llibertat (40.8%). # In[8]: penes = original.query("genere != '--'").\ groupby(["genere","pena_cat"])["pena_cat"].count().\ unstack("genere") penes["Dones %"] = penes["Dona"].div(sum(penes["Dona"])) penes["Homes %"] = penes["Home"].div(sum(penes["Home"])) def highlight_max(s): is_max = s == s.max() return ['background-color:yellow' if v else '' for v in is_max] penes.style.apply(highlight_max,axis=0).\ format("{:.1%}",subset=['Dones %','Homes %']) # ### Pas 5: Categoritzar origen i residència # # Categories: # # - b - Barcelona # - c - Catalunya (fora de la província de Barcelona) # - e - Espanya (fora de Catalunya) # - i - internacional (fora d'Espanya) # - ? - altres / no consta # # # In[9]: def cat_naix(cas) : if cas.prov_naix == '--' and cas.pais_naix == '--' : naix="?" if cas.prov_naix == "Barcelona" : naix="b" elif cas.ca_naix == "Catalunya" : naix="c" elif cas.pais_naix == "Espanya" : naix="e" else: naix="i" return naix def cat_res(cas) : if cas.prov_res == '--' and cas.pais_res == '--' : return "?" if cas.prov_res == "Barcelona" : res="b" elif cas.ca_res == "Catalunya" : res="c" elif cas.pais_res.find("Espanya")>-1 : res="e" elif cas.pais_res.find("Sense domicili fix")>-1 : res="e" else : res="i" return res original["cat_naix"]=original.apply(cat_naix,axis=1) original["cat_res"]=original.apply(cat_res,axis=1) # ### Primera anàlisi: Relació entre lloc de naixement i de residència # # Aplicant les nostres categories, a primer cop d’ull es noten poques diferències entre homes i dones. Queda per investigar. # In[10]: naix_res = original.query("genere != '--'").\ groupby(["cat_naix","cat_res","genere"])["nom"].\ count().\ unstack("cat_res") # La taula mostra el percentatge entre totes les dones o tots els homes d'aquesta categoria de residència. Exemple: **28.2%** de les dones (i **16.0%** dels homes) nascudes a Catalunya fora de la província de Barcelona resideixen a la província de Barcelona. # # In[11]: naix_res = naix_res.div(naix_res.sum(axis=1),axis=0) def highlight_max(s): is_max = s == s.max() return ['font-weight:bold' if v else '' for v in is_max] naix_res.style.apply(highlight_max,axis=1, subset=(pd.IndexSlice['c'],pd.IndexSlice['b'])).\ format("{:.1%}") # ### Pas 6: executades o no? # In[12]: def cat_execut(a) : if str(a).find("executa") > -1 : return "exec" else : return "no exec" original["af_cat"]=original["afusellades"].apply(cat_execut) # ### Primera análisi: Pena de mort i execucions # # La majoria de les 41 dones condemnades a pena de mort no van ser executades. Entre els homes, una quarta part dels 4376 condemnats a mort no van ser executats segons les dades. # In[13]: pena_mort = original.query("pena_cat == '00 mort'").\ groupby(["genere","af_cat"])["pena_cat"].count().\ unstack("genere") pena_mort_sum=pena_mort.sum(axis=0) pena_mort_sum.name="sum" pena_mort = pena_mort.append(pena_mort_sum) pena_mort["sum"] = pena_mort.sum(axis=1) pena_mort # ### Pas 7: Guardar dades processats # In[14]: original.to_msgpack("data/processat.msg") # ### Primera anàlisi: Relaciò entre "Tipus procediment 1" i "Tipus procediment 2" # # Trobem aquestes dues columnes de les dades originals difícils d'interpretar. # In[15]: original["proc_1_simple"]=original["proc_1"].apply(lambda a: a.replace(" []","")) original.groupby(["proc_2","proc_1_simple"])["nom"].count().unstack("proc_1_simple").fillna(' ') # ### Primera anàlisi: Relaciò entre "Tipus procediment 1" i "pena" # # # In[16]: original.groupby(["pena_cat","proc_1_simple","genere"])["nom"].\ count().\ unstack("proc_1_simple").\ unstack("genere").\ fillna(0).\ style.format("{:0g}")