Spaces:
Running
Running
Update data_cleaning.py
Browse files- data_cleaning.py +168 -124
data_cleaning.py
CHANGED
@@ -1,124 +1,168 @@
|
|
1 |
-
import chardet
|
2 |
-
import pandas as pd
|
3 |
-
import regex
|
4 |
-
|
5 |
-
|
6 |
-
def iniciar(file_path):
|
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 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import chardet
|
2 |
+
import pandas as pd
|
3 |
+
import regex
|
4 |
+
|
5 |
+
def processar_arquivo(uploaded_file):
|
6 |
+
def iniciar(file_path):
|
7 |
+
"""
|
8 |
+
A function that detects the encoding of a file and reads the file using the detected encoding.
|
9 |
+
"""
|
10 |
+
# Detectar a codificação do arquivo
|
11 |
+
raw_data = uploaded_file.read()
|
12 |
+
result = chardet.detect(raw_data)
|
13 |
+
encoding = result["encoding"]
|
14 |
+
print(f"Detected encoding: {encoding}")
|
15 |
+
|
16 |
+
# Ler o arquivo com a codificação detectada
|
17 |
+
uploaded_file.seek(0) # Reset file pointer to the beginning
|
18 |
+
csv_data = uploaded_file.read().decode(encoding)
|
19 |
+
return csv_data
|
20 |
+
|
21 |
+
def limpa_rci1(texto):
|
22 |
+
"""
|
23 |
+
Cleans up the given text by removing unwanted parts.
|
24 |
+
"""
|
25 |
+
# Remover partes indesejadas
|
26 |
+
sub1 = r"(^e-SUS.+\nMIN(.+\n+){2}.+)|(^CBO.+\n(.+\n+){2}.+)|(^Não\sinf.+\n+Identif.+\nDes.+\nDes.+\nDes.+\nRes.+\n+Iden.+$)|(^Não\sin.+\n+Ident.+Cor$)|(^Não\sin.+\n+Ident.+\nDesc.+\nBra.+\nNat(.+\n+){34}.+)|(^Inf.+\nDesc.+\nAdult.+\n(.+\n+){10}.+)|(^Inf.+\n(Des.+\n){3}.+$)|(^Inf.+\nDesc.+\n(Tem\salg.+\n){1}.+$)|(^Inf.+\nA\slist.+\nDes(.+\n+){8}.+$)|(^Desc.+\nÉ.+\nPossu(.+\n*)*)|(^Não\sinf.+;0.+$)|(;;;;;|;;;;|Ident.+(-|/)\s)|"
|
27 |
+
sub2 = r"(^C.*(rin|card|resp).+\n.+\n.+[os]\s)|(;;;\nT.+\nT.+$)|(;Sim|(?<=[az];);|\ssabe;|\s.\sEnfisema)|(^Participa.+$|Poss.+de\s|(?<=privado.;\d\d\d);.+|Poss.+de\s|(?<=privado.;\d\d\d\d);.+)|((Desc.+\n){3}Resp.+$)|(Etnia.+\nD.+\nNã.+$)|(Nacio.+\nDesc.+\nB.+\nNat.+\nEst.+$)|(Infor.+\nDesc.+\nCôn(.+\n){31}Inf.+$)|Deseja\sinf.+$|(Infor.+\nDesc.+\nEmpreg(.+\n){10}.+$)|Intelec.+/\s|((Está\s(com\s)?))|(^Condiç.+\nD.+$)|((Faz\suso.+e\s)|PIC;.+|Tem\s|ou\steve\s|Teve\s|internação.+\nUsa\splant.+$|\s/\sderrame|diagnóst.+de\s)"
|
28 |
+
rx_marc = sub1 + "|" + sub2
|
29 |
+
texto = regex.sub(rx_marc, "", texto, flags=regex.MULTILINE)
|
30 |
+
tira = r"(;;;)"
|
31 |
+
texto = regex.sub(tira, "", texto, flags=regex.MULTILINE)
|
32 |
+
tira = r"(;;)"
|
33 |
+
texto = regex.sub(tira, ";", texto, flags=regex.MULTILINE)
|
34 |
+
return texto
|
35 |
+
|
36 |
+
def limpa_rci2(texto):
|
37 |
+
"""
|
38 |
+
Cleans up the given text by removing unwanted parts.
|
39 |
+
"""
|
40 |
+
sub2 = r"(^C.*(rin|card|resp).+\n.+\n.+[os]\s)|(;;;\nT.+\nT.+$)|(;Sim|(?<=[az];);|\ssabe;|\s.\sEnfisema)|(\d+{10}\s-\s)|(^Participa.+$|Poss.+de\s|(?<=privado.;\d\d\d);.+|Poss.+de\s|(?<=privado.;\d\d\d\d);.+)|((Desc.+\n){3}Resp.+$)|(Etnia.+\nD.+\nNã.+$)|(Nacio.+\nDesc.+\nB.+\nNat.+\nEst.+$)|(Infor.+\nDesc.+\nCôn(.+\n){31}Inf.+$)|Deseja\sinf.+$|(Infor.+\nDesc.+\nEmpreg(.+\n){10}.+$)|Intelec.+/\s|((Está\s(com\s)?))|(^Condiç.+\nD.+$)|((Faz\suso.+e\s)|PIC;.+|Tem\s|ou\steve\s|Teve\s|internação.+\nUsa\splant.+$|\s/\sderrame|diagnóst.+de\s)"
|
41 |
+
|
42 |
+
texto = regex.sub(sub2, "", texto, flags=regex.MULTILINE)
|
43 |
+
tira = r"(;;;)"
|
44 |
+
texto = regex.sub(tira, "", texto, flags=regex.MULTILINE)
|
45 |
+
tira = r"(;;)"
|
46 |
+
texto = regex.sub(tira, "; ", texto, flags=regex.MULTILINE)
|
47 |
+
tira = r"(;$)"
|
48 |
+
texto = regex.sub(tira, "", texto, flags=regex.MULTILINE)
|
49 |
+
tira = r"(\s\d+{10}\s-\s)"
|
50 |
+
texto = regex.sub(tira, "", texto, flags=regex.MULTILINE)
|
51 |
+
return texto
|
52 |
+
|
53 |
+
def separa_grupos(texto):
|
54 |
+
"""
|
55 |
+
A function that uses a regular expression to extract various groups from the input text.
|
56 |
+
"""
|
57 |
+
# Expressão regular ajustada para capturar vários grupos
|
58 |
+
grupos = r"""
|
59 |
+
(?P<Data>(Data;\d+/\d+/\d+))|
|
60 |
+
(?P<Head>(Equ.+;.+)|Profiss.+l;\w+|((Saíd.+;\d+)|(Cidadã.+;\d+)))|
|
61 |
+
(?P<Idade>(^Menos.+(?=;0)|^[0-9][0-9]\s\w).+(?=;0))|
|
62 |
+
(?P<genero>(Masc.+;\d+|Fem.+;\d+))|
|
63 |
+
(?P<cor>(^(Bra.+;\d+|Pret.+;\d+|Amar.+;\d+|Par.+;\d+|Indí.+;\d+)))|
|
64 |
+
(?P<deficiencia>(^(Audi.+a;\d+|Fís.+a;\d+|Cogn.+a;\d+|Vis.+l;\d+|Out.+;\d+)))|
|
65 |
+
(?P<doencas>(^(hipert.+al;\d+|diab.+s;\d+|gesta.+e;\d+|acam.+o;\d+|domici.+o;\d+|fuma.+e;\d+|saú.+e;\d+|Asm.+;\d+|DPO.+;\d+|Insufic.+ca;\d+|Insufic.+al;\d+)))|
|
66 |
+
(?P<Escola>(Desc.+o;Quant.+\nCre.+e;\d+|Pr.+;\d+|Classe.+;\d+|Ens.+;\d+|Sup.+r;\d+|Alf.+;\d+|Nenhu.+;\d+))|
|
67 |
+
(?P<transgen>(Homos.+\);\d+|Bisse.+l;\d+|Hom.+trans.+;\d+|Mul.+trans.+;\d+|Traves.+i;\d+|Transgê.+o;\d+|Não-B.+o;\d+))|
|
68 |
+
"""
|
69 |
+
|
70 |
+
# Compilar a expressão regular com as flags re.VERBOSE e re.MULTILINE para maior legibilidade
|
71 |
+
pattern = regex.compile(grupos, regex.VERBOSE | regex.MULTILINE)
|
72 |
+
|
73 |
+
matches = pattern.finditer(texto)
|
74 |
+
grupos_enc = {
|
75 |
+
"Data": [],
|
76 |
+
"Head": [],
|
77 |
+
"Idade": [],
|
78 |
+
"genero": [],
|
79 |
+
"cor": [],
|
80 |
+
"deficiencia": [],
|
81 |
+
"doencas": [],
|
82 |
+
"Escola": [],
|
83 |
+
"transgen": []
|
84 |
+
}
|
85 |
+
|
86 |
+
for match in matches:
|
87 |
+
for group_name, group_value in match.groupdict().items():
|
88 |
+
if group_value and group_name in grupos_enc:
|
89 |
+
grupos_enc[group_name].append(group_value)
|
90 |
+
|
91 |
+
return grupos_enc
|
92 |
+
|
93 |
+
def criar_dataframe(grupos_encontrados):
|
94 |
+
"""
|
95 |
+
Create dataframes based on the groups found in `grupos_encontrados`.
|
96 |
+
"""
|
97 |
+
dataframes = {}
|
98 |
+
for grupo, valores in grupos_encontrados.items():
|
99 |
+
if grupo == "Idade":
|
100 |
+
df = pd.DataFrame(valores, columns=["Descrição"])
|
101 |
+
df["Masculino"] = df["Descrição"].apply(lambda x: x.split(";")[1])
|
102 |
+
df["Feminino"] = df["Descrição"].apply(lambda x: x.split(";")[2])
|
103 |
+
df["Descrição"] = df["Descrição"].apply(lambda x: x.split(";")[0])
|
104 |
+
else:
|
105 |
+
# Tratar casos onde os dados são separados por '\n'
|
106 |
+
novos_valores = []
|
107 |
+
for valor in valores:
|
108 |
+
partes = valor.split("\n")
|
109 |
+
novos_valores.extend(partes)
|
110 |
+
df = pd.DataFrame(novos_valores, columns=["Descrição"])
|
111 |
+
df["Valor"] = df["Descrição"].apply(lambda x: x.split(";")[-1])
|
112 |
+
df["Descrição"] = df["Descrição"].apply(
|
113 |
+
lambda x: ";".join(x.split(";")[:-1]))
|
114 |
+
df["Descrição"] = df["Descrição"].apply(lambda x: x.replace(";", ""))
|
115 |
+
dataframes[grupo] = df
|
116 |
+
return dataframes
|
117 |
+
|
118 |
+
def renomear_escola(df_escola):
|
119 |
+
"""
|
120 |
+
Renomeia as descrições da coluna 'Descrição' do DataFrame df_escola.
|
121 |
+
"""
|
122 |
+
renomeacoes = {
|
123 |
+
"Creche": "Creche",
|
124 |
+
"Pré-escola (exceto CA)": "Pré-escola",
|
125 |
+
"Classe de alfabetização": "Alfabetização",
|
126 |
+
"Ensino fundamental 1ª a 4ª séries": "Fundamental 1ª-4ª",
|
127 |
+
"Ensino fundamental 5ª a 8ª séries": "Fundamental 5ª-8ª",
|
128 |
+
"Ensino fundamental completo": "Fund. Completo",
|
129 |
+
"Ensino fundamental especial": "Fund. Especial",
|
130 |
+
"Ensino fundamental EJA - séries iniciais (supletivo 1ª a 4ª)": "Fund. EJA Iniciais",
|
131 |
+
"Ensino fundamental EJA - séries finais (supletivo 5ª a 8ª)": "Fund. EJA Finais",
|
132 |
+
"Ensino médio, médio 2º ciclo (científico, técnico e etc)": "Médio/Científico/Técnico",
|
133 |
+
"Ensino médio especial": "Médio Especial",
|
134 |
+
"Ensino médio EJA (supletivo)": "Médio EJA",
|
135 |
+
"Alfabetização para adultos (Mobral, etc)": "Alfabetização Adultos",
|
136 |
+
"Nenhum": "Nenhum"
|
137 |
+
}
|
138 |
+
|
139 |
+
df_escola["Descrição"] = df_escola["Descrição"].map(renomeacoes)
|
140 |
+
return df_escola
|
141 |
+
|
142 |
+
def limpar_dfs(dataframes, regex_pattern, replacement):
|
143 |
+
"""
|
144 |
+
Aplica uma regex de limpeza em todos os DataFrames.
|
145 |
+
"""
|
146 |
+
for key, df in dataframes.items():
|
147 |
+
df["Descrição"] = df["Descrição"].astype(str).apply(lambda x: regex.sub(regex_pattern, replacement, x))
|
148 |
+
return dataframes
|
149 |
+
|
150 |
+
# Leitura e limpeza do arquivo CSV
|
151 |
+
csv_data = iniciar(uploaded_file)
|
152 |
+
csv_data_limpo = limpa_rci1(csv_data)
|
153 |
+
|
154 |
+
# Separação dos grupos
|
155 |
+
grupos_encontrados = separa_grupos(csv_data_limpo)
|
156 |
+
|
157 |
+
# Criação dos dataframes
|
158 |
+
dataframes = criar_dataframe(grupos_encontrados)
|
159 |
+
|
160 |
+
# Renomear descrições do DataFrame de escolaridade
|
161 |
+
dataframes["Escola"] = renomear_escola(dataframes["Escola"])
|
162 |
+
|
163 |
+
# Aplicar limpeza final nos DataFrames
|
164 |
+
clean_final = r"(\sativ\w+)|(\sde\scid.+o)|(iciê.+ia)|((?<=rans)gên.+o|omem|ulher|ário|Homoss.+\(|\))|(\d{10}\s-\s)"
|
165 |
+
substituicao = ""
|
166 |
+
dataframes = limpar_dfs(dataframes, clean_final, substituicao)
|
167 |
+
|
168 |
+
return dataframes
|