Infra#

El trabajo se hace sobre los datos del FIUBA-Map, que están en un spreadsheet. Acá hacemos un get, ordenamos los jsons de cada usuario en un dataframe de Pandas, y lo guardamos en un pickle para que el resto de los archivos tengan acceso a la base de datos.

Exporta un pickle con los datos de todas las carreras, para los análisis globales, y un pickle para solo una carrera en particular, para los análisis particulares.

from config import CARRERA, PADRON

from tqdm.notebook import tqdm
import json
import pandas as pd

SHEET_ID = '1b6h2RApBs2xbN6-eGVvxH68EALKDklvS91fb7d_IVz4'
SHEET_TABS = {
    'REGISTROS': 2103959160,
    'USUARIOS': 102021014,
}
REGISTROS_URL = f'https://docs.google.com/spreadsheets/d/{SHEET_ID}/export?format=csv&gid={SHEET_TABS["REGISTROS"]}'
USUARIOS_URL = f'https://docs.google.com/spreadsheets/d/{SHEET_ID}/export?format=csv&gid={SHEET_TABS["USUARIOS"]}'
# Empezamos cargando todos los datos (los usuarios y los mapas están en dos tablas distintas)
df_registros = pd.read_csv(REGISTROS_URL)
df_registros.drop("Timestamp", axis=1, inplace=True)
df_registros.dropna(inplace=True, how="any")
display(df_registros.dropna().tail(3))

df_usuarios = pd.read_csv(USUARIOS_URL)
df_usuarios.drop("Timestamp", axis=1, inplace=True)
df_usuarios.dropna(inplace=True, how="all")
display(df_usuarios.dropna().sample(3))
Padron Carrera Mapa
4639 10007 sistemas {"materias":[{"id":"CBC","nota":0},{"id":"81.0...
4640 99568 industrial {"materias":[{"id":"CBC","nota":0},{"id":"81.0...
4641 97589 quimica {"materias":[{"id":"CBC","nota":0},{"id":"61.0...
Padron Carrera Orientacion Final de Carrera
1263 123123 informatica Sistemas Distribuidos tpp
5398 <script>alert("a")</script> informatica Sistemas Distribuidos tesis
388 108671 informatica Sistemas Distribuidos tpp
### Testing purposes: en vez de laburar con toooodos los datos, laburemos sólo con los integrantes del grupo
# df_usuarios = df_usuarios[df_usuarios['Padron'].isin(["100029", "101696", "101109", "0000"])]
# Mergeamos!
df_mergeado = df_usuarios.merge(df_registros)
df_mergeado.dropna().sample(3)
Padron Carrera Orientacion Final de Carrera Mapa
2273 104112 informatica Sistemas Distribuidos tpp {"materias":[{"id":"CBC","nota":0},{"id":"62.0...
453 108397 informatica Sistemas Distribuidos tesis {"materias":[{"id":"CBC28","nota":6},{"id":"CB...
1821 110119 informatica Gestión Industrial de Sistemas tesis {"materias":[{"id":"CBC28","nota":5},{"id":"CB...
df_mergeado.describe()
Padron Carrera Orientacion Final de Carrera Mapa
count 4620 4620 714 1768 4620
unique 3842 15 5 2 3903
top 4444 industrial Sistemas Distribuidos tpp {"materias":[{"id":"CBC","nota":0,"cuatri":-1}...
freq 13 1201 307 1398 158
# Ahora, desempaquetamos la columna "Mapa" (un JSON que contiene notas, metadata, de todo...) 
#   y finalmente lleguemos al df que vamos a usar durante todo el tp

df = df_mergeado
new_df = pd.DataFrame()
for idx in tqdm(df.index):
    json_mapa = json.loads(df.loc[idx]['Mapa'])
    
    for k in json_mapa.keys():
        if not json_mapa[k]: 
            continue
        if k == "materias":
            df_json = pd.json_normalize(json_mapa, k, record_prefix="materia_")
        else:
            df_json = pd.DataFrame({k: [json_mapa[k]]})
        df_json["Padron"] = df.loc[idx]['Padron']
        df_json["Carrera"] = df.loc[idx]['Carrera']
        new_df = pd.concat([new_df, df_json])

df = df.merge(new_df, how="outer", on=['Padron', 'Carrera'])
df.drop('Mapa', axis=1, inplace=True)
# Hace mucho tiempo, el fiuba map tenia un feature que se llamaba "materia_cuatri" (en vez del nuevo "materia_cuatrimestre")
# En donde el usuario seteaba en cuantos N cuatris iba a cursar X materia, en vez de setear el cuatri exacto
# Como ya no se usa en el upstream, no es lo correcto que lo utilicemos en el análisis de datos
if 'materia_cuatri' in df.columns: df.drop('materia_cuatri', axis=1, inplace=True)
df.sample(3)
Padron Carrera Orientacion Final de Carrera materia_id materia_nota aplazos materia_cuatrimestre checkboxes optativas
103603 99149 civil NaN NaN 94.01 4.0 NaN NaN NaN NaN
46661 39463898 civil NaN NaN 81.01 4.0 NaN NaN NaN NaN
94981 99428 industrial NaN tpp 91.12 7.0 NaN 2019.5 NaN NaN
# Exportamos todo a un hermoso pickle
df.to_pickle('fiuba-map-data-all.pickle')
# Exportamos sólo la información de la carrera a otro pickle
df[df['Carrera'] == CARRERA].to_pickle('fiuba-map-data.pickle')