From 8c63d0cbe362a227943d8268aad6cc095fdc6449 Mon Sep 17 00:00:00 2001 From: Pedro Castro Date: Thu, 15 Aug 2024 15:40:23 -0300 Subject: [PATCH] Ideb 2023: atualizar tabela `municipio` e `escola` (#736) --- models/br_inep_ideb/br_inep_ideb__escola.sql | 1 + .../br_inep_ideb/br_inep_ideb__municipio.sql | 1 + models/br_inep_ideb/code/ideb_2023.py | 264 +++++++++++++++++- models/br_inep_ideb/schema.yml | 4 - 4 files changed, 258 insertions(+), 12 deletions(-) diff --git a/models/br_inep_ideb/br_inep_ideb__escola.sql b/models/br_inep_ideb/br_inep_ideb__escola.sql index b5e1c579..57bbcd78 100644 --- a/models/br_inep_ideb/br_inep_ideb__escola.sql +++ b/models/br_inep_ideb/br_inep_ideb__escola.sql @@ -1,4 +1,5 @@ {{ config(alias="escola", schema="br_inep_ideb", materialized="table") }} + select safe_cast(ano as int64) ano, safe_cast(sigla_uf as string) sigla_uf, diff --git a/models/br_inep_ideb/br_inep_ideb__municipio.sql b/models/br_inep_ideb/br_inep_ideb__municipio.sql index d906cfcc..1d1cf09d 100644 --- a/models/br_inep_ideb/br_inep_ideb__municipio.sql +++ b/models/br_inep_ideb/br_inep_ideb__municipio.sql @@ -1,4 +1,5 @@ {{ config(alias="municipio", schema="br_inep_ideb", materialized="table") }} + select safe_cast(ano as int64) ano, safe_cast(sigla_uf as string) sigla_uf, diff --git a/models/br_inep_ideb/code/ideb_2023.py b/models/br_inep_ideb/code/ideb_2023.py index ddbc17bd..28fc807c 100644 --- a/models/br_inep_ideb/code/ideb_2023.py +++ b/models/br_inep_ideb/code/ideb_2023.py @@ -16,12 +16,12 @@ URLS = { "brasil": "https://download.inep.gov.br/ideb/resultados/divulgacao_brasil_ideb_2023.zip", "regioes_estados": "https://download.inep.gov.br/ideb/resultados/divulgacao_regioes_ufs_ideb_2023.zip", - # "municipio_anos_iniciais": "https://download.inep.gov.br/educacao_basica/portal_ideb/planilhas_para_download/2021/divulgacao_anos_iniciais_municipios_2021.zip", - # "municipio_anos_finais": "https://download.inep.gov.br/educacao_basica/portal_ideb/planilhas_para_download/2021/divulgacao_anos_finais_municipios_2021.zip", - # "municipio_em": "https://download.inep.gov.br/educacao_basica/portal_ideb/planilhas_para_download/2021/divulgacao_ensino_medio_municipios_2021.zip", - # "escola_anos_iniciais": "https://download.inep.gov.br/educacao_basica/portal_ideb/planilhas_para_download/2021/divulgacao_anos_iniciais_escolas_2021.zip", - # "escola_anos_finais": "https://download.inep.gov.br/educacao_basica/portal_ideb/planilhas_para_download/2021/divulgacao_anos_finais_escolas_2021.zip", - # "escola_em": "https://download.inep.gov.br/educacao_basica/portal_ideb/planilhas_para_download/2021/divulgacao_ensino_medio_escolas_2021.zip", + "municipio_anos_iniciais": "https://download.inep.gov.br/ideb/resultados/divulgacao_anos_iniciais_municipios_2023.zip", + "municipio_anos_finais": "https://download.inep.gov.br/ideb/resultados/divulgacao_anos_finais_municipios_2023.zip", + "municipio_em": "https://download.inep.gov.br/ideb/resultados/divulgacao_ensino_medio_municipios_2023.zip", + "escola_anos_iniciais": "https://download.inep.gov.br/ideb/resultados/divulgacao_anos_iniciais_escolas_2023.zip", + "escola_anos_finais": "https://download.inep.gov.br/ideb/resultados/divulgacao_anos_finais_escolas_2023.zip", + "escola_em": "https://download.inep.gov.br/ideb/resultados/divulgacao_ensino_medio_escolas_2023.zip", } for _, url in URLS.items(): @@ -35,8 +35,8 @@ os.makedirs(output_dir, exist_ok=True) - with zipfile.ZipFile(file_path, "r") as zip_ref: - zip_ref.extractall(output_dir) + with zipfile.ZipFile(file_path, "r") as z: + z.extractall(output_dir) XLSX_BR = os.path.join( TMP, "brasil", "divulgacao_brasil_ideb_2023", "divulgacao_brasil_ideb_2023.xlsx" @@ -272,3 +272,251 @@ df_uf_updated.to_csv(OUTPUT_UF, index=False) tb_uf.create(OUTPUT_UF, if_table_exists="replace", if_storage_data_exists="replace") + +# Municipios + +XLSX_MUN_ANOS_INICIAIS = os.path.join( + TMP, + "municipio_anos_iniciais", + "divulgacao_anos_iniciais_municipios_2023", + "divulgacao_anos_iniciais_municipios_2023.xlsx", +) + +XLSX_MUN_ANOS_FINAIS = os.path.join( + TMP, + "municipio_anos_finais", + "divulgacao_anos_finais_municipios_2023", + "divulgacao_anos_finais_municipios_2023.xlsx", +) + +XLSX_MUN_EM = os.path.join( + TMP, + "municipio_em", + "divulgacao_ensino_medio_municipios_2023", + "divulgacao_ensino_medio_municipios_2023.xlsx", +) + +df_municipio_latest = ( + pd.concat( + [ + pd.read_excel(path, skiprows=9)[ + [ + *[i for i in COMMON_RENAMES.keys() if i != "rede"], + *["SG_UF", "CO_MUNICIPIO", "REDE"], + ] + ] + .rename( + columns={ + "SG_UF": "sigla_uf", + "REDE": "rede", + "CO_MUNICIPIO": "id_municipio", + }, + errors="raise", + ) # type: ignore + .rename(columns=COMMON_RENAMES, errors="raise") + .assign(anos_escolares=table_name) + for table_name, path in { + "anos_iniciais": XLSX_MUN_ANOS_INICIAIS, + "anos_finais": XLSX_MUN_ANOS_FINAIS, + "em": XLSX_MUN_EM, + }.items() + ] + ) + .pipe(lambda d: d.loc[d["rede"].notna()]) + .assign(ano=2023, projecao=np.nan) +) + +df_municipio_latest.head() + +df_municipio_latest["rede"].unique() + +df_municipio_latest["rede"] = ( + df_municipio_latest["rede"] + .str.lower() + .replace( + { + "pública": "publica", + } + ) +) + +df_municipio_latest["anos_escolares"].unique() + +df_municipio_latest["anos_escolares"] = df_municipio_latest["anos_escolares"].replace( + { + "anos_iniciais": "iniciais (1-5)", + "anos_finais": "finais (6-9)", + "em": "todos (1-4)", + } +) + +df_municipio_latest["ensino"] = df_municipio_latest["anos_escolares"].apply( + lambda v: "medio" if v == "todos (1-4)" else "fundamental" +) + +df_municipio_latest["ensino"].unique() + +assert len(df_municipio_latest["sigla_uf"].unique()) == 27 + +df_municipio_latest["id_municipio"] = ( + df_municipio_latest["id_municipio"].astype(int).astype(str) +) + +assert ( + df_municipio_latest[["id_municipio", "rede", "anos_escolares"]] + .value_counts(dropna=False) + .reset_index()["count"] + .unique()[0] + == 1 +) + +df_municipio_latest.head() + +tb_municipio = bd.Table(dataset_id="br_inep_ideb", table_id="municipio") + +tb_municipio_cols_from_bq = tb_municipio._get_columns_from_bq(mode="prod") + +assert len(tb_municipio_cols_from_bq["partition_columns"]) == 0 + +tb_municipio_order_cols: list[str] = [ + i["name"] for i in tb_municipio_cols_from_bq["columns"] +] + +df_municipio_upstream = bd.read_sql( + "select * from `basedosdados.br_inep_ideb.municipio`", + billing_project_id="basedosdados-dev", +) + +df_municipio_updated = pd.concat( + [df_municipio_latest[tb_municipio_order_cols], df_municipio_upstream] # type: ignore +) + +OUTPUT_MUNICIPIO = os.path.join(OUTPUT, "municipio.csv") + +df_municipio_updated.to_csv(OUTPUT_MUNICIPIO, index=False) + +tb_municipio.create( + OUTPUT_MUNICIPIO, if_table_exists="replace", if_storage_data_exists="replace" +) + +# Escolas + +XLSX_ESCOLAS_ANOS_INICIAIS = os.path.join( + TMP, + "escola_anos_iniciais", + "divulgacao_anos_iniciais_escolas_2023", + "divulgacao_anos_iniciais_escolas_2023.xlsx", +) + +XLSX_ESCOLAS_ANOS_FINAIS = os.path.join( + TMP, + "escola_anos_finais", + "divulgacao_anos_finais_escolas_2023", + "divulgacao_anos_finais_escolas_2023.xlsx", +) + +XLSX_ESCOLAS_EM = os.path.join( + TMP, + "escola_em", + "divulgacao_ensino_medio_escolas_2023", + "divulgacao_ensino_medio_escolas_2023.xlsx", +) + +df_escolas_latest = ( + pd.concat( + [ + pd.read_excel(path, skiprows=9)[ + [ + *[i for i in COMMON_RENAMES.keys() if i != "rede"], + *["SG_UF", "CO_MUNICIPIO", "REDE", "ID_ESCOLA"], + ] + ] + .rename( + columns={ + "SG_UF": "sigla_uf", + "REDE": "rede", + "CO_MUNICIPIO": "id_municipio", + "ID_ESCOLA": "id_escola", + }, + errors="raise", + ) # type: ignore + .rename(columns=COMMON_RENAMES, errors="raise") + .assign(anos_escolares=table_name) + for table_name, path in { + "anos_iniciais": XLSX_ESCOLAS_ANOS_INICIAIS, + "anos_finais": XLSX_ESCOLAS_ANOS_FINAIS, + "em": XLSX_ESCOLAS_EM, + }.items() + ] + ) + .pipe(lambda d: d.loc[d["rede"].notna()]) + .assign(ano=2023, projecao=np.nan) +) + +df_escolas_latest.head() + +df_escolas_latest["rede"].unique() + +df_escolas_latest["rede"] = df_escolas_latest["rede"].str.lower() + +df_escolas_latest["anos_escolares"].unique() + +df_escolas_latest["anos_escolares"] = df_escolas_latest["anos_escolares"].replace( + { + "anos_iniciais": "iniciais (1-5)", + "anos_finais": "finais (6-9)", + "em": "todos (1-4)", + } +) + +df_escolas_latest["ensino"] = df_escolas_latest["anos_escolares"].apply( + lambda v: "medio" if v == "todos (1-4)" else "fundamental" +) + +df_escolas_latest["ensino"].unique() + +assert len(df_escolas_latest["sigla_uf"].unique()) == 27 + +df_escolas_latest["id_municipio"] +df_escolas_latest["id_escola"] + +df_escolas_latest["id_municipio"] = ( + df_escolas_latest["id_municipio"].astype(int).astype(str) +) + +df_escolas_latest["id_escola"] = df_escolas_latest["id_escola"].astype(int).astype(str) + +assert ( + df_escolas_latest[["rede", "anos_escolares", "id_escola"]] + .value_counts(dropna=False) + .reset_index()["count"] + .unique()[0] + == 1 +) + +df_escolas_latest.head() + +tb_escola = bd.Table(dataset_id="br_inep_ideb", table_id="escola") + +tb_escola_cols_from_bq = tb_escola._get_columns_from_bq(mode="prod") + +assert len(tb_escola_cols_from_bq["partition_columns"]) == 0 + +tb_escola_order_cols: list[str] = [i["name"] for i in tb_escola_cols_from_bq["columns"]] + +df_escola_upstream = bd.read_sql( + "select * from `basedosdados.br_inep_ideb.escola`", + billing_project_id="basedosdados-dev", +) + +df_escolas_updated = pd.concat( + [df_escolas_latest[tb_escola_order_cols], df_escola_upstream] # type: ignore +) + +OUTPUT_ESCOLA = os.path.join(OUTPUT, "escola.csv") + +df_escolas_updated.to_csv(OUTPUT_ESCOLA, index=False) + +tb_escola.create( + OUTPUT_ESCOLA, if_table_exists="replace", if_storage_data_exists="replace" +) diff --git a/models/br_inep_ideb/schema.yml b/models/br_inep_ideb/schema.yml index f30b84f7..1c45a527 100644 --- a/models/br_inep_ideb/schema.yml +++ b/models/br_inep_ideb/schema.yml @@ -97,10 +97,6 @@ models: field: id_municipio - name: id_escola description: ID Escola - INEP - tests: - - relationships: - to: ref('br_bd_diretorios_brasil__escola') - field: id_escola - name: rede description: Rede Escolar tests: