Source code for seriesbr.ipea.series

import pandas as pd

from datetime import datetime
from .metadata import get_metadata, IpeaMetadata
from seriesbr.utils import session, dates
from dateutil.relativedelta import relativedelta
from typing import Tuple, TypedDict, Optional


[docs]def get_series( code: str, start: str = None, end: str = None, last_n: int = None, ) -> pd.DataFrame: """ Get multiple IPEA time series. Parameters ---------- code : str Series identifier. start : str, optional Initial date. end : str, optional Final date. Returns ------- pandas.DataFrame """ metadata = get_metadata(code) url, params = build_url(code, start, end, last_n, metadata) response = session.get(url, params=params) json = response.json() df = build_df(json, code) return df
def build_df(json: dict, code: str) -> pd.DataFrame: json = json["value"] df = pd.DataFrame(json) df["VALDATA"] = df["VALDATA"].str[:-6] df["VALDATA"] = pd.to_datetime(df["VALDATA"], format="%Y-%m-%dT%H:%M:%S") df = df.rename(columns={"VALDATA": "Date"}) df = df.set_index("Date") df["VALVALOR"] = pd.to_numeric(df["VALVALOR"], errors="coerce") df = df.rename(columns={"VALVALOR": code}) return df IpeaUrlParams = TypedDict( "IpeaUrlParams", { "$select": str, "$filter": str, }, total=False, ) def build_url( code: str, start: Optional[str], end: Optional[str], last_n: Optional[int], metadata: IpeaMetadata, ) -> Tuple[str, IpeaUrlParams]: params: IpeaUrlParams params = {"$select": "VALDATA,VALVALOR"} url = ( f"http://ipeadata2-homologa.ipea.gov.br/api/v1/ValoresSerie(SERCODIGO='{code}')" ) max_date = ( datetime.fromisoformat(metadata["SERMAXDATA"]) if metadata["SERMAXDATA"] else datetime.utcnow() ) min_date = ( datetime.fromisoformat(metadata["SERMINDATA"]) if metadata["SERMINDATA"] else datetime.utcnow() ) if last_n: periodicity = metadata["PERNOME"] if periodicity == "Anual": offset_date = max_date - relativedelta(years=last_n) elif periodicity == "Quadrienal": offset_date = max_date - relativedelta(years=4 * last_n) elif periodicity == "Quinquenal": offset_date = max_date - relativedelta(years=5 * last_n) elif periodicity == "Decenal": offset_date = max_date - relativedelta(years=10 * last_n) elif periodicity == "Trimestral": offset_date = max_date - relativedelta(months=3 * last_n) elif periodicity == "Mensal": offset_date = max_date - relativedelta(months=last_n) elif periodicity == "Irregular": offset_date = max_date else: offset_date = max_date params["$filter"] = f"VALDATA gt {offset_date.isoformat()}" else: if start: start = ( dates.parse_start_date(start) .replace(tzinfo=min_date.tzinfo) .isoformat() ) if end: end = dates.parse_end_date(end).replace(tzinfo=max_date.tzinfo).isoformat() date_filter = ipea_filter_by_date(start, end) if date_filter: params["$filter"] = date_filter return url, params def ipea_filter_by_date(start: str = None, end: str = None) -> str: """ Filter an IPEA time series by date. Parameters ---------- start : str Start date string. End : str End date string. Returns ------- str A string to filter by dates. Examples -------- >>> url.ipea_filter_by_date("2019-01-01T00:00:00-00:00", "2019-02-01T00:00:00-00:00") 'VALDATA ge 2019-01-01T00:00:00-00:00 and VALDATA le 2019-02-01T00:00:00-00:00' """ def filter_by_start_date(start): return f"VALDATA ge {start}" def filter_by_end_date(start): return f"VALDATA le {start}" if start and end: return filter_by_start_date(start) + " and " + filter_by_end_date(end) elif start: return filter_by_start_date(start) elif end: return filter_by_end_date(end) return ""