Extract, Transform and Load¶
O pacote ufesp busca atualizar o valor, obtendo dados na internet, tratando-os e disponibilizando uma forma facilitada para consulta.
Em linhas gerais, é um trabalho de ETL (Extract, Transform and Load).
Abaixo será demonstrado alguns dos comando utilizando as bibliotecas pandas para obter essas informações.
O script tem possibilita testar ajustes e alterações para serem incorporadas as funções e classes do pacote.
In [1]:
Copied!
import pandas as pd
import ufesp
from ufesp.paths import data_path
import pandas as pd
import ufesp
from ufesp.paths import data_path
In [2]:
Copied!
# Lemos todas as tabelas da página
dfs = pd.read_html(io='https://legislacao.fazenda.sp.gov.br/Paginas/ValoresDaUFESP.aspx')
# Selecionamos apenas a tabela que queremos
df = dfs[3]
# Resultado
df.head()
# Lemos todas as tabelas da página
dfs = pd.read_html(io='https://legislacao.fazenda.sp.gov.br/Paginas/ValoresDaUFESP.aspx')
# Selecionamos apenas a tabela que queremos
df = dfs[3]
# Resultado
df.head()
Out[2]:
| PERÍODO | VALOR EM R$ | BASE LEGAL | |
|---|---|---|---|
| 0 | de 01/01/2026 A 31/12/2026 | 3842 | Comunicado DICAR-88/ 25, de 17-12-2025 |
| 1 | de 01/01/2025 A 31/12/2025 | 37,02 | Comunicado DICAR-88/24, de 17-12-2024 |
| 2 | de 01/01/2024 A 31/12/2024 | 35,36 | Comunicado DICAR-93/23, de 19-12-2023 |
| 3 | de 01/01/2023 A 31/12/2023 | 34,26 | Comunicado DICAR-90/22, de 19-12-2022 |
| 4 | de 01/01/2022 A 31/12/2022 | 31,97 | Comunicado DICAR-89/21, de 17-12-2021 |
In [3]:
Copied!
# Renomeia Colunas
df = df.rename(
mapper={
'VALOR EM R$': 'valor',
'PERÍODO': 'periodo',
'BASE LEGAL': 'base_legal',
},
axis=1,
inplace=False,
)
# Renomeia Colunas
df = df.rename(
mapper={
'VALOR EM R$': 'valor',
'PERÍODO': 'periodo',
'BASE LEGAL': 'base_legal',
},
axis=1,
inplace=False,
)
Trata os dados de valor.
In [4]:
Copied!
df['valor'] = df['valor'].replace(',', '', regex=True)
df['valor'] = df['valor'].replace('\u200b', '', regex=True)
df['valor'] = df['valor'].astype(float)
df['valor'] = df['valor'] / 100
# Results
df.info()
df.head()
df['valor'] = df['valor'].replace(',', '', regex=True)
df['valor'] = df['valor'].replace('\u200b', '', regex=True)
df['valor'] = df['valor'].astype(float)
df['valor'] = df['valor'] / 100
# Results
df.info()
df.head()
<class 'pandas.DataFrame'> RangeIndex: 30 entries, 0 to 29 Data columns (total 3 columns): # Column Non-Null Count Dtype --- ------ -------------- ----- 0 periodo 30 non-null str 1 valor 30 non-null float64 2 base_legal 25 non-null str dtypes: float64(1), str(2) memory usage: 852.0 bytes
Out[4]:
| periodo | valor | base_legal | |
|---|---|---|---|
| 0 | de 01/01/2026 A 31/12/2026 | 38.42 | Comunicado DICAR-88/ 25, de 17-12-2025 |
| 1 | de 01/01/2025 A 31/12/2025 | 37.02 | Comunicado DICAR-88/24, de 17-12-2024 |
| 2 | de 01/01/2024 A 31/12/2024 | 35.36 | Comunicado DICAR-93/23, de 19-12-2023 |
| 3 | de 01/01/2023 A 31/12/2023 | 34.26 | Comunicado DICAR-90/22, de 19-12-2022 |
| 4 | de 01/01/2022 A 31/12/2022 | 31.97 | Comunicado DICAR-89/21, de 17-12-2021 |
Trata os dados de período.
In [5]:
Copied!
df['periodo'] = df['periodo'].replace('de ', '', regex=True)
df['periodo'] = df['periodo'].replace(' a ', ' A ', regex=True)
df['periodo'] = df['periodo'].replace('\u200b', '', regex=True)
df['periodo'] = df['periodo'].replace('\xa0', ' ', regex=True)
# Results
df.info()
df.head()
df['periodo'] = df['periodo'].replace('de ', '', regex=True)
df['periodo'] = df['periodo'].replace(' a ', ' A ', regex=True)
df['periodo'] = df['periodo'].replace('\u200b', '', regex=True)
df['periodo'] = df['periodo'].replace('\xa0', ' ', regex=True)
# Results
df.info()
df.head()
<class 'pandas.DataFrame'> RangeIndex: 30 entries, 0 to 29 Data columns (total 3 columns): # Column Non-Null Count Dtype --- ------ -------------- ----- 0 periodo 30 non-null str 1 valor 30 non-null float64 2 base_legal 25 non-null str dtypes: float64(1), str(2) memory usage: 852.0 bytes
Out[5]:
| periodo | valor | base_legal | |
|---|---|---|---|
| 0 | 01/01/2026 A 31/12/2026 | 38.42 | Comunicado DICAR-88/ 25, de 17-12-2025 |
| 1 | 01/01/2025 A 31/12/2025 | 37.02 | Comunicado DICAR-88/24, de 17-12-2024 |
| 2 | 01/01/2024 A 31/12/2024 | 35.36 | Comunicado DICAR-93/23, de 19-12-2023 |
| 3 | 01/01/2023 A 31/12/2023 | 34.26 | Comunicado DICAR-90/22, de 19-12-2022 |
| 4 | 01/01/2022 A 31/12/2022 | 31.97 | Comunicado DICAR-89/21, de 17-12-2021 |
In [6]:
Copied!
df[['data_inicio', 'data_fim']] = df['periodo'].str.split(
pat='A',
n=1,
expand=True,
)
df[['data_inicio', 'data_fim']] = df['periodo'].str.split(
pat='A',
n=1,
expand=True,
)
In [7]:
Copied!
# Ajusta Data do Início
df['data_inicio'] = df['data_inicio'].str.strip()
df['data_inicio'] = pd.to_datetime(df['data_inicio'], format='%d/%m/%Y')
# Ajusta Data do Fim
df['data_fim'] = df['data_fim'].str.strip()
df['data_fim'] = pd.to_datetime(df['data_fim'], format='%d/%m/%Y')
# Ajusta
df['ano_mes'] = pd.to_datetime(df['data_inicio']).dt.to_period('M')
# Results
df.info()
df.head()
# Ajusta Data do Início
df['data_inicio'] = df['data_inicio'].str.strip()
df['data_inicio'] = pd.to_datetime(df['data_inicio'], format='%d/%m/%Y')
# Ajusta Data do Fim
df['data_fim'] = df['data_fim'].str.strip()
df['data_fim'] = pd.to_datetime(df['data_fim'], format='%d/%m/%Y')
# Ajusta
df['ano_mes'] = pd.to_datetime(df['data_inicio']).dt.to_period('M')
# Results
df.info()
df.head()
<class 'pandas.DataFrame'> RangeIndex: 30 entries, 0 to 29 Data columns (total 6 columns): # Column Non-Null Count Dtype --- ------ -------------- ----- 0 periodo 30 non-null str 1 valor 30 non-null float64 2 base_legal 25 non-null str 3 data_inicio 30 non-null datetime64[us] 4 data_fim 30 non-null datetime64[us] 5 ano_mes 30 non-null period[M] dtypes: datetime64[us](2), float64(1), period[M](1), str(2) memory usage: 1.5 KB
Out[7]:
| periodo | valor | base_legal | data_inicio | data_fim | ano_mes | |
|---|---|---|---|---|---|---|
| 0 | 01/01/2026 A 31/12/2026 | 38.42 | Comunicado DICAR-88/ 25, de 17-12-2025 | 2026-01-01 | 2026-12-31 | 2026-01 |
| 1 | 01/01/2025 A 31/12/2025 | 37.02 | Comunicado DICAR-88/24, de 17-12-2024 | 2025-01-01 | 2025-12-31 | 2025-01 |
| 2 | 01/01/2024 A 31/12/2024 | 35.36 | Comunicado DICAR-93/23, de 19-12-2023 | 2024-01-01 | 2024-12-31 | 2024-01 |
| 3 | 01/01/2023 A 31/12/2023 | 34.26 | Comunicado DICAR-90/22, de 19-12-2022 | 2023-01-01 | 2023-12-31 | 2023-01 |
| 4 | 01/01/2022 A 31/12/2022 | 31.97 | Comunicado DICAR-89/21, de 17-12-2021 | 2022-01-01 | 2022-12-31 | 2022-01 |
Trata os dados de base legal.
In [8]:
Copied!
# Ajustes
df['base_legal'] = df['base_legal'].replace('\u200b', '', regex=True)
df['base_legal'] = df['base_legal'].replace('\xa0', ' ', regex=True)
df['base_legal'] = df['base_legal'].replace('88/ 25', '88/25', regex=True)
df['base_legal'] = df['base_legal'].str.strip()
# Results
df.info()
df.head()
# Ajustes
df['base_legal'] = df['base_legal'].replace('\u200b', '', regex=True)
df['base_legal'] = df['base_legal'].replace('\xa0', ' ', regex=True)
df['base_legal'] = df['base_legal'].replace('88/ 25', '88/25', regex=True)
df['base_legal'] = df['base_legal'].str.strip()
# Results
df.info()
df.head()
<class 'pandas.DataFrame'> RangeIndex: 30 entries, 0 to 29 Data columns (total 6 columns): # Column Non-Null Count Dtype --- ------ -------------- ----- 0 periodo 30 non-null str 1 valor 30 non-null float64 2 base_legal 25 non-null str 3 data_inicio 30 non-null datetime64[us] 4 data_fim 30 non-null datetime64[us] 5 ano_mes 30 non-null period[M] dtypes: datetime64[us](2), float64(1), period[M](1), str(2) memory usage: 1.5 KB
Out[8]:
| periodo | valor | base_legal | data_inicio | data_fim | ano_mes | |
|---|---|---|---|---|---|---|
| 0 | 01/01/2026 A 31/12/2026 | 38.42 | Comunicado DICAR-88/25, de 17-12-2025 | 2026-01-01 | 2026-12-31 | 2026-01 |
| 1 | 01/01/2025 A 31/12/2025 | 37.02 | Comunicado DICAR-88/24, de 17-12-2024 | 2025-01-01 | 2025-12-31 | 2025-01 |
| 2 | 01/01/2024 A 31/12/2024 | 35.36 | Comunicado DICAR-93/23, de 19-12-2023 | 2024-01-01 | 2024-12-31 | 2024-01 |
| 3 | 01/01/2023 A 31/12/2023 | 34.26 | Comunicado DICAR-90/22, de 19-12-2022 | 2023-01-01 | 2023-12-31 | 2023-01 |
| 4 | 01/01/2022 A 31/12/2022 | 31.97 | Comunicado DICAR-89/21, de 17-12-2021 | 2022-01-01 | 2022-12-31 | 2022-01 |
In [9]:
Copied!
# Results
df = df[
[
'data_inicio',
'data_fim',
'ano_mes',
'valor',
'base_legal',
]
].copy()
# Results
df.info()
df.head()
# Results
df = df[
[
'data_inicio',
'data_fim',
'ano_mes',
'valor',
'base_legal',
]
].copy()
# Results
df.info()
df.head()
<class 'pandas.DataFrame'> RangeIndex: 30 entries, 0 to 29 Data columns (total 5 columns): # Column Non-Null Count Dtype --- ------ -------------- ----- 0 data_inicio 30 non-null datetime64[us] 1 data_fim 30 non-null datetime64[us] 2 ano_mes 30 non-null period[M] 3 valor 30 non-null float64 4 base_legal 25 non-null str dtypes: datetime64[us](2), float64(1), period[M](1), str(1) memory usage: 1.3 KB
Out[9]:
| data_inicio | data_fim | ano_mes | valor | base_legal | |
|---|---|---|---|---|---|
| 0 | 2026-01-01 | 2026-12-31 | 2026-01 | 38.42 | Comunicado DICAR-88/25, de 17-12-2025 |
| 1 | 2025-01-01 | 2025-12-31 | 2025-01 | 37.02 | Comunicado DICAR-88/24, de 17-12-2024 |
| 2 | 2024-01-01 | 2024-12-31 | 2024-01 | 35.36 | Comunicado DICAR-93/23, de 19-12-2023 |
| 3 | 2023-01-01 | 2023-12-31 | 2023-01 | 34.26 | Comunicado DICAR-90/22, de 19-12-2022 |
| 4 | 2022-01-01 | 2022-12-31 | 2022-01 | 31.97 | Comunicado DICAR-89/21, de 17-12-2021 |