Un transformer es un script en Python ejecutable, auto-contenido y auto-reproducible. Esencialmente son "recetas" fácilmente aplicables a un dataset,
compuesto por una serie de instrucciones (funciones) para mutarlo, junto con las definiciones exactas de cada una de ellas. De esta manera, cada archivo
describe en sí mismo su comportamiento, siendo así expresivo respecto de su funcionalidad, pero también fácilmente ejecutable en un proceso de automatización.
Cada uno de estos archivos tiene como objetivo generar CSVs listos para ser graficados por el sitio web de ArgenData, por lo que
implica un proceso de normalización más fuerte que la armonización previa (Ver etl). Junto con la modificación estructural del dataset, se deja sólo lo imprescindible para
que el gráfico pueda ser visualizado, generando así archivos mucho más livianos.
El trabajo en este repositorio esta definido por un sistema de archivos que se estructura alrededor de cada uno de los tópicos de Argendata
├── TOPICO
├── ...
├── AGROPE
│ ├── mappings.json
│ ├── TOPICO_gXX_transformer.py
│ └── ...
└── TRANEN
├── mappings.json
├── TRANEN_g01_transformer.py
├── TRANEN_g02_transformer.py
├── TRANEN_g03_transformer.py
├── TRANEN_g04_transformer.py
├── TRANEN_g05_transformer.py
├── TRANEN_g06_transformer.py
├── TRANEN_g07_transformer.py
├── TRANEN_g08_transformer.py
├── TRANEN_g09_transformer.py
├── TRANEN_g10_transformer.py
├── TRANEN_g11_transformer.py
├── TRANEN_g12_transformer.py
├── TRANEN_g13_transformer.py
├── TRANEN_g14_transformer.py
├── TRANEN_g15_transformer.py
├── TRANEN_g16_transformer.py
├── TRANEN_g17_transformer.py
├── TRANEN_g18_transformer.py
└── TRANEN_g19_transformer.py
Cada dataset de Argendata tiene un nombre sustantivo y uno simplificado que funciona como id, que sigue un formato del tipo TOPICO_g01.csv.
Para nuestro ejemplo, a TRANEN_g01.csv le corresponde matriz_prim_mundo_historic_larga.csv. El flujo de reproducitibilidad implica en los hechos que se trata de dos datasets diferentes:
-
(i) uno que es el resultado del proceso que generan los investigadores para luego ser reproducidos en el proceso de ETL. En nuestro ejemplo, este se realiza a partir del script
matriz_prim_mundo_historic_larga.Ren el repositorio ETL, facilitado por la librería deRargendataR -
(ii) otro que es re transformado para darle la forma requerida por el Frontend en el proceso de graficación. Esta tarea es facilitada por los tarnsformers. En nuestro ejemplo se trata de
TRANEN_g01_transformer.pyfacilitado por la biblioteca dePythondata-transformers
Estas equivalencias entre versiones de .csv están contenidas en un mapeo dentro de cada subdirectorio de topicos en el repositiorio de transformers: mappings.json
from pandas import DataFrame
from data_transformers import chain, transformer
# DEFINITIONS_START
@transformer.convert
def query(df: DataFrame, condition: str):
df = df.query(condition)
return df
@transformer.convert
def rename_cols(df: DataFrame, map):
df = df.rename(columns=map)
return df
@transformer.convert
def sort_values(df: DataFrame, how: str, by: list):
if how not in ['ascending', 'descending']:
raise ValueError('how must be either "ascending" or "descending"')
return df.sort_values(by=by, ascending=how == 'ascending')
# DEFINITIONS_END
# PIPELINE_START
pipeline = chain(
query(condition='tipo_energia != "Total"'),
rename_cols(map={'tipo_energia': 'indicador', 'valor_en_twh': 'valor'}),
sort_values(how='ascending', by=['anio', 'indicador'])
)
# PIPELINE_END
# start()
# RangeIndex: 836 entries, 0 to 835
# Data columns (total 4 columns):
# # Column Non-Null Count Dtype
# --- ------ -------------- -----
# 0 anio 836 non-null int64
# 1 tipo_energia 836 non-null object
# 2 valor_en_twh 836 non-null float64
# 3 porcentaje 836 non-null float64
#
# | | anio | tipo_energia | valor_en_twh | porcentaje |
# |---:|-------:|:-----------------|---------------:|-------------:|
# | 0 | 1800 | Otras renovables | 0 | 0 |
#
# ------------------------------
#
# query(condition='tipo_energia != "Total"')
# Index: 760 entries, 0 to 759
# Data columns (total 4 columns):
# # Column Non-Null Count Dtype
# --- ------ -------------- -----
# 0 anio 760 non-null int64
# 1 tipo_energia 760 non-null object
# 2 valor_en_twh 760 non-null float64
# 3 porcentaje 760 non-null float64
#
# | | anio | tipo_energia | valor_en_twh | porcentaje |
# |---:|-------:|:-----------------|---------------:|-------------:|
# | 0 | 1800 | Otras renovables | 0 | 0 |
#
# ------------------------------
#
# rename_cols(map={'tipo_energia': 'indicador', 'valor_en_twh': 'valor'})
# Index: 760 entries, 0 to 759
# Data columns (total 4 columns):
# # Column Non-Null Count Dtype
# --- ------ -------------- -----
# 0 anio 760 non-null int64
# 1 indicador 760 non-null object
# 2 valor 760 non-null float64
# 3 porcentaje 760 non-null float64
#
# | | anio | indicador | valor | porcentaje |
# |---:|-------:|:-----------------|--------:|-------------:|
# | 0 | 1800 | Otras renovables | 0 | 0 |
#
# ------------------------------
#
# sort_values(how='ascending', by=['anio', 'indicador'])
# Index: 760 entries, 76 to 227
# Data columns (total 4 columns):
# # Column Non-Null Count Dtype
# --- ------ -------------- -----
# 0 anio 760 non-null int64
# 1 indicador 760 non-null object
# 2 valor 760 non-null float64
# 3 porcentaje 760 non-null float64
#
# | | anio | indicador | valor | porcentaje |
# |---:|-------:|:----------------|--------:|-------------:|
# | 76 | 1800 | Biocombustibles | 0 | 0 |
#
# ------------------------------
#