def get_series_df_from_panel( df_panel, series, time_index_freq, time_format="%Y-%m-%d", time_field="indice_tiempo", series_id_field="serie_id", values_field="valor", ): """Convierte tabla con id, fecha y valor en distribución de TS. Args: df_panel (pd.DataFrame): Tabla con columnas de id de series, fecha y valor de observaciones. series (dict): Donde los keys son "field_id" de series y los values son "field_title" de las series. time_field (str): Campo que tiene la fecha. time_format (str): Formato en el que hay que parsear la fecha. series_id_field (str): Campo que tiene el id de la serie. values_field (str): Campo que tiene los valores de las observaciones. return: pd.DataFrame """ # parsea el campo de fechas al tipo datetime df_panel[time_field] = pd.to_datetime(df_panel[time_field], format=time_format) # se queda solo con las series elegidas df = df_panel[df_panel[series_id_field].isin(series.keys())] # construye un período continuo para el índice de tiempo, el más largo period_range = pd.date_range( min(df.indice_tiempo), max(df.indice_tiempo), freq=freq_iso_to_pandas(time_index_freq), ) # cambia ids por titulos que sean nombres de campos al pivotar df["serie_id"] = df.serie_id.apply(series.get) # convierte el panel en una tabla de series de tiempo data = df.pivot_table(columns="serie_id", index="indice_tiempo", values="valor") # convierte el indice de tiempo a comienzos de periodos try: data.index = data.index.to_period( freq=freq_iso_to_pandas(time_index_freq, "start")).to_timestamp() except Exception as e: data.index = data.index.to_period( freq=freq_iso_to_pandas(time_index_freq, "end")).to_timestamp() # completa indice de tiempo con periodos faltante para que sea continuo df_series = pd.DataFrame(index=period_range, data=data) return df_series
def init_df(self, distribution, fields): """Inicializa el DataFrame del CSV de la distribución pasada, seteando el índice de tiempo correcto y validando las columnas dentro de los datos Args: distribution (Distribution): modelo de distribución válido fields (dict): diccionario con estructura titulo: serie_id """ df = read_distribution_csv_as_df(distribution) self.drop_null_or_missing_fields_from_df(df, fields) identifiers = [fields[name] for name in df.columns] data = df.values freq = freq_iso_to_pandas( get_time_index_periodicity(distribution, fields)) new_index = pd.date_range(df.index[0], df.index[-1], freq=freq) # Chequeo de series de días hábiles (business days) if freq == constants.DAILY_FREQ and new_index.size > df.index.size: new_index = pd.date_range(df.index[0], df.index[-1], freq=constants.BUSINESS_DAILY_FREQ) return pd.DataFrame(index=new_index, data=data, columns=identifiers)
def validate_df_shape(df, distrib_meta, _catalog): periodicity = None for field in distrib_meta["field"]: if field.get("specialType") == "time_index": periodicity = field.get("specialTypeDetail") freq = freq_iso_to_pandas(periodicity) new_index = pd.date_range(df.index[0], df.index[-1], freq=freq) columns = df.columns data = np.array(df) try: pd.DataFrame(index=new_index, data=data, columns=columns) except ValueError: if freq == "D": freq = "B" new_index = pd.date_range(df.index[0], df.index[-1], freq=freq) try: pd.DataFrame(index=new_index, data=data, columns=columns) return except ValueError: pass raise ce.DistributionBadDataError( distrib_meta["identifier"], df.index[0], df.index[-1], periodicity, len(new_index), len(data), )
def init_df(self, distribution, fields): """Inicializa el DataFrame del CSV de la distribución pasada, seteando el índice de tiempo correcto y validando las columnas dentro de los datos Args: distribution (Distribution): modelo de distribución válido fields (dict): diccionario con estructura titulo: serie_id """ df = read_distribution_csv(distribution) # Borro las columnas que no figuren en los metadatos for column in df.columns: if column not in fields: df.drop(column, axis='columns', inplace=True) columns = [fields[name] for name in df.columns] data = df.values freq = freq_iso_to_pandas( get_time_index_periodicity(distribution, fields)) new_index = pd.date_range(df.index[0], df.index[-1], freq=freq) # Chequeo de series de días hábiles (business days) if freq == constants.DAILY_FREQ and new_index.size > df.index.size: new_index = pd.date_range(df.index[0], df.index[-1], freq=constants.BUSINESS_DAILY_FREQ) return pd.DataFrame(index=new_index, data=data, columns=columns)
def generate_df_time_index(df: pd.DataFrame, time_index: Field): periodicity = get_distribution_time_index_periodicity(time_index) freq = freq_iso_to_pandas(periodicity) new_index = pd.date_range(df.index[0], df.index[-1], freq=freq) # Chequeo de series de días hábiles (business days) if freq == constants.DAILY_FREQ and new_index.size > df.index.size: new_index = pd.date_range(df.index[0], df.index[-1], freq=constants.BUSINESS_DAILY_FREQ) return new_index