Finally I have implemented a mixed solution: def get_sas_data(sas, i, chunk_size, table, container):
'''
Descarga datos partición a partición desde una tabla SAS.
Parámetros:
+ sas (SASconnection): Objeto de conexión SAS.
+ i (int): Índice de la iteración (comienza en 0).
+ chunk_size (int): Número de filas por partición.
+ table (str): Nombre de la tabla SAS.
+ container (str): Nombre del contenedor Azure.
Ejemplo de llamada:
get_sas_data(SASconnection, 18, 500000, 'RECIBOS_POLIZA_201412', 'GENREC')
Retorno (pd.DataFrame):
+ DF de Pandas con los datos de cada partición.
'''
def segregate_types(type_dict):
'''
Separa las columnas de tipo fecha del resto.
Parámetros:
+ type_dict (Dict[str, str]): Diccionario con pares "nombre de la columna"/"tipo de datos".
Ejemplo de llamada:
segregate_types({'fecha': 'date', ..., 'PRIMERA_ACCION': 'str'})
Retorno (Tuple[List[str], Dict[str, str]]):
+ Una lista con los nombres de las columnas de tipo fecha.
+ El diccionario original sin los pares de tipo fecha.
'''
date_cols = [col for col, data_type in type_dict.items() if data_type == 'date']
for col in date_cols: type_dict.pop(col)
return date_cols, type_dict
def convert_dates(series):
'''
Convierte una serie de Pandas a formato "datetime".
Parámetros:
+ series (pd.Series): Serie con valores semánticamente de tipo fecha pero en otro formato.
Ejemplo de llamada:
convert_dates(pd.Series([20088.0, ..., 20088.0])
Retorno (pd.Series):
+ La serie con el tipo de dato corregido.
'''
if series.dtypes == 'float64': return pd.to_datetime('1960-01-01') + pd.to_timedelta(series.fillna(0), unit='D')
else: return pd.to_datetime(series, errors='coerce', dayfirst=True)
lower_bound = (i * chunk_size) + 1
upper_bound = (i + 1) * chunk_size
chunk_range = {'firstobs': lower_bound, 'obs': upper_bound}
type_dict = Config.CONFIG_TABLES.get(table, {}) #Diccionario de formatos de config_prod.yml.
date_cols, type_dict = segregate_types(type_dict.copy()) #Diccionario de formatos sin los campos de tipo fecha.
try: #La transformación de campos que no sean fechas, si aplica, ocurre a la vez que se descarga la información de SAS a DF.
if type_dict: df = sas.sd2df_DISK(table=table, libref=container, dtype=type_dict, my_fmts=True, dsopts=chunk_range)
else: df = sas.sasdata(table=table, libref=container, dsopts=chunk_range).to_frame()
except ValueError as e:
print(f'Error al cargar la tabla desde SAS: {str(e)}')
raise ConnectionError
for col in date_cols: df[col] = convert_dates(df[col]) #La transformación de fechas, si aplica, ocurre siempre tras obtener el DF.
return df Docstrings and comments are in Spanish but I think the code is pretty self explanatory. First I segregate dates from the rest of the dictionary: date_cols, type_dict = segregate_types(type_dict.copy()) I force the conversion of strings -or whatsoever type that is supported; in my case, at least for the moment, just strings- during the download from SAS to DF: if type_dict: df = sas.sd2df_DISK(table=table, libref=container, dtype=type_dict, my_fmts=True, dsopts=chunk_range) Then, once I already have a DF, I force the conversion of dates: for col in date_cols: df[col] = convert_dates(df[col])
... View more