# ---
# jupyter:
#   jupytext:
#     text_representation:
#       extension: .py
#       format_name: light
#       format_version: '1.5'
#       jupytext_version: 1.14.4
#   kernelspec:
#     display_name: venv_playground
#     language: python
#     name: venv_playground
# ---

# + [markdown] tags=[]
# ## **Introdução a Pandas**
# -

# - [Pandas](https://pandas.pydata.org/) é uma ferramenta *open source* contruída em cima do python, para manipular com dados de forma rápida, poderosa, flexível e fácil.
#
# - Seu nome vem de uma brincadeira com a frase *Python data analysis*.
#
# - Esse projeto foi criado por um pesquisador (<NAME>) enquanto ele trabalhava na [AQR Capital](https://www.aqr.com/) (Uma empresa de investimentos).
#
#
# - [Pandas vs Outras ferramentas](https://pandas.pydata.org/docs/getting_started/comparison/index.html).
#
# - [Documentação - versão - 1.3.4 em PDF](https://pandas.pydata.org/pandas-docs/version/1.3.4/pandas.pdf).
#
# ---
#
# [Começando com o Pandas](https://pandas.pydata.org/docs/getting_started/index.html)
#
# Exemplo por <NAME> de como utilizar a ferramenta/biblioteca/projeto/API: [Vídeo](https://www.youtube.com/watch?v=_T8LGqJtuGc) 

# +
import numpy as np
import pandas as pd

from time import time

from IPython.display import display

# + [markdown] tags=[]
# ## **Objeto DataFrame**
# -

# <center><img src="figures/dataframe.png" align="center" width=220/></center>
#

# +
tabela = [[2,2,3],
           [7,5,1],
           [9,3,4]]

df = pd.DataFrame(tabela)
display(df)

# +
tabela = {"limao":[1,2,3], 
          "feijao":[5,8,0],
          "batata":[7,6,9]}

df = pd.DataFrame(tabela)
display(df)

# +
tabela = [[2,2,3],
           [7,5,1],
           [9,3,4]]

df = pd.DataFrame(tabela, columns=["a", "b", "c"], index=["00", "01", "10"])
display(df)

# + [markdown] tags=[]
# ## **Objeto Series**
# -

# <center><img src="figures/series.png" align="center" width=100/></center>

# +
a = [1,2,3,4]

pd.Series(a)

# +
b = {1:1,2:2,3:7,9:4}

pd.Series(b)
# -

# <font color="orange">**LEMBRAR!**</font>
# > - Para importar o pacote utilize - import pandas as pd
# > - Uma tabela de dados é denominada DataFrame
# >  - Cada coluna em um DataFrame é denominada Series
# >  - DataFrame e Series são os principais **OBJETOS** da biblioteca.
#   

# + [markdown] tags=[]
# ## **Explicando os tipos de dados**
# -

# | Pandas dtype   | Python type   | NumPy type   | Usage  |
# |---|---|---|---|
# | object     | str or mixed  | string_, unicode_, mixed types   |  Text or mixed numeric and non-numeric values |
# | int64      | int |  int_, int8, int16, int32, int64, uint8, uint16, uint32, uint64 | Integer numbers  |
# | float64    | float  | float64 	float 	float_, float16, float32, float64  | Floating point numbers  |
# | bool       |  bool |  bool_ |  True/False values |
# | datetime64 | --  | datetime64[ns]  | Date and time values |
# | timedelta[ns] | --  | NA  | Differences between two datetimes  |
# | category   | -- | NA |  Finite list of text values |
#
# --- 
# Capacity:
#
# - Int16: (-32,768 to +32,767)
#
# - Int32: (-2,147,483,648 to +2,147,483,647)
#
# - Int64: (-9,223,372,036,854,775,808 to +9,223,372,036,854,775,807)

# Suponha que você tem um DataFrame com uma coluna idade:

aux = [np.random.randint(200) for i in range(10000)]
col_idades = pd.DataFrame(aux)
col_idades.info()

# Por *default* o pandas resolveu utilizar o tipo de dado ```int64``` para representar essa coluna, isso significa que podemos representar do número ```-9,223,372,036,854,775,808``` ao ```+9,223,372,036,854,775,80```.
#
# Entretanto sabemos que não deve ter ninguém com mais de 200 anos de vida atualmente, logo não precisamos conseguir representar todos esses número. Dessa forma, podemos utilizar um tipo de dado mais coerente como exemplo ```Int16``` que vai de ```-32,768``` a ```+32,767```, dimunindo a quantidade de memória utilizada por esse objeto.

col_idades.astype({0:"int16"}).info()

# Estamos utilizando praticamente 3x menos memória para armazenar o mesmo dado. Então não podemos ir adiante? Sera que não podemos utilizar o int8 para representar essa coluna?

col_idades.astype({0:"int8"}).info()

# Nossa! Ficou ainda melhor.... <font color="orange"><b>Cuidado!!!</b></font> olhe o que aconteceu com a coluna.

col_idades.astype({0:"int8"}).describe()

# Está dizendo aqui que o minimo é -128??? mas como assim oq aconteceu??? Vamos lá...
#
#
# ```int8``` significa que temos 8 bits, isso significa que temos $2^8 = 256$ números que podem ser representados.
#
# Intuitivamente podemos pensar que o range seria então de 0 a 255. 
#
# Entretanto, o tipo de dado ```int8``` no python também considera os negativos, logo a representação correta é de -128 a 127, conforme a função describe nos mostra. 
#
# Dizemos que ocorreu overflow... e queremos evitar isso. Cada caso é um caso escolha o tipo de dado mais coerente para sua aplicação.

# + [markdown] tags=[]
# ## **Formatos de leitura e escrita** 
# -

# <center><img src="figures/read_dataframe_formats.png" align="center" width=550/></center>

df = pd.read_csv("data/data_sample2.csv")
df

# Kaggle dataset: [Open food Facts](https://www.kaggle.com/openfoodfacts/world-food-facts/data)

# O formato salvo impacta na performance do arquivo. Como podemos ver a seguir:

# +
from time import time

tick = time()
df = pd.read_csv("data/en.openfoodfacts.org.products.tsv", sep="\t", low_memory=False)
tock = time()
print(tock - tick)
# -

tick = time()
df = pd.read_parquet("data/en.openfoodfacts.org.products.parquet")
tock = time()
print(tock - tick)

# Vamos entender mais sobre isso nas próximas aulas.

# + [markdown] tags=[]
# ## **Descrevendo o DataFrame**
#
# - head 
# - tail 
# - info
# - astype
# - describe
# -

# mostras as ```n``` primeiras linhas de um DataFrame.
df.head(1)

# mostras as ```n``` últimas linhas de um DataFrame.
df.tail(1)

# +
# Retorna algumas informações, dentre elas a quantidade de memória que é ocupado no DataFrame.

df.info()
# -

# Retorna estatisticas básicas do DataFrame.
df.describe()

# + [markdown] tags=[]
# # **Exercicios** 
# -

# 1. Leia o arquivo ```exercise_1.csv``` e responda as seguintes questões.
#
# - Quantas linhas e colunas ele tem? 
#
# - Quais são os tipos de dados de cada coluna? 
#
# - Quanto ocupa esse objeto em memória? 

# +
df = pd.read_csv("data_exercise/exercise1.csv", sep = ";")
# on progress

qtd_rows, qtd_columns = df.shape
print(f"Quantidade de linhas desse DataFrame é {qtd_rows}")
print("Segue os Tipos de dados de cada coluna.")
print(df.dtypes)
print("Quantidade de memória ocupada pelo DataFrame.")
print(df.info())
# -

# 2. Lei o arquivo ```exercise2.csv``` [Ref](https://dados.gov.br/dataset/cursos-de-graduacao5)
#
# - Quantas linhas e colunas ele tem? 
#
# - Quais são os tipos de dados de cada coluna? 
#
# - Quanto ocupa esse objeto em memória? Você acha que precisa de tudo isso?

# +
df = pd.read_csv("data_exercise/exercise2.csv", encoding="latin1")

qtd_rows, qtd_columns = df.shape
print(f"Quantidade de linhas desse DataFrame é {qtd_rows}")
print("Segue os Tipos de dados de cada coluna.")
print(df.dtypes)
print("Quantidade de memória ocupada pelo DataFrame.")
print(df.info())
print("A quantidade de memória utilizada depende da aplicação.")
# -

# 3. Lei o arquivo ```exercise3.json``` [Ref](http://landpage-h.cgu.gov.br/dadosabertos/index.php?url=http://repositorio.dados.gov.br/seges/raio-x/cargos-funcoes-perfil.csv)
#
# - Quantas linhas e colunas ele tem? 
#
# - Quais são os tipos de dados de cada coluna? 
#
# - Quanto ocupa esse objeto em memória? Você acha que precisa de tudo isso?

# +
df = pd.read_json("data_exercise/exercise3.json", orient="records")

qtd_rows, qtd_columns = df.shape
print(f"Quantidade de linhas desse DataFrame é {qtd_rows}")
print("Segue os Tipos de dados de cada coluna.")
print(df.dtypes)
print("Quantidade de memória ocupada pelo DataFrame.")
print(df.info())
print("A quantidade de memória utilizada depende da aplicação.")
# -

# 4. Lei o arquivo ```exercise4.json``` em um pandas DataFrame [Ref](http://landpage-h.cgu.gov.br/dadosabertos/index.php?url=http://repositorio.dados.gov.br/seges/raio-x/cargos-funcoes-perfil.csv)
#
#
# - Quais são os tipos de dados de cada coluna? 
#
# - Quanto ocupa esse objeto em memória? Você acha que precisa de tudo isso?

df = pd.read_json("data_exercise/exercise4.json", orient="split")
qtd_rows, qtd_columns = df.shape
print(f"Quantidade de linhas desse DataFrame é {qtd_rows}")
print("Segue os Tipos de dados de cada coluna.")
print(df.dtypes)
print("Quantidade de memória ocupada pelo DataFrame.")
print(df.info())
print("A quantidade de memória utilizada depende da aplicação.")

# 5. Crie um DataFrame para cadastro de funcionarios com as colunas nome, idade e sexo baseado em listas e baseado em dicionários. Os dados você pode inventar.
#

# baseado em lista
columns = ["nome", "idade", "sexo"]
data = [["Rodrigo", 25, "M"],
        ["Isabela", 22, "F"],
        ["Samuel", 19, "M"]]
pd.DataFrame(data, columns=columns)

# baseado em dicionario
# baseado em lista
data = {
        "nome":  ["Rodrigo", "Isabela", "Samuel"],
        "idade": [25, 19, 22],
        "sexo":  ["M", "F", "M"]
       }
pd.DataFrame(data)

# 6. Leia o arquivo x e salve a cada 100 mil linhas um novo arquivo até o número de linhas da arquivo x terminar

df = pd.read_csv("data_exercise/exercise_huge_file.csv")

# +
nrows_per_file = 100_000
nrows = df.shape[0]
iter_number = int(np.ceil(nrows / nrows_per_file))

for i in range(iter_number):
    lower_limit = i*nrows_per_file
    upper_limit = nrows_per_file*(i+1)
    filtered_df = df.iloc[lower_limit:upper_limit,:]
    filtered_df.to_csv(f"exercise6/new_file{(i+1)}.csv", index = False)
# -

# Depois de um processamento é interessante checar os limites.

pd.read_csv("exercise6/new_file1.csv").shape

pd.read_csv("exercise6/new_file18.csv").shape

# Extra:
#
# Você consegue transformar as tabelas do Wikipidia em um DataFrame?
#
# - Dica: Talvez precise instalar algumas bibliotecas extras, como exemplo, lxml, html5lib, bs4 ...
#
# [TABELA](https://en.wikipedia.org/wiki/Minnesota)

dfs_internet = pd.read_html("https://en.wikipedia.org/wiki/Minnesota")

dfs_internet[1].head()

# <font color="orange">**LEMBRAR!**</font>
# > - csv é um formato bastante comum, fiquem esperto com o separador.
# > - Muitas vezes é necessário saber encoding do nosso dado.
# > - Independente do formato (json, ..., html) precisa ser uma tabela para transformar em um DataFrame. 

# + [markdown] tags=[]
# ## **Onde posso aprender mais?** 
# -

#
#
# [Comnuidade Pandas](https://pandas.pydata.org/docs/getting_started/tutorials.html). Aqui tem livros, palestras, tutoriais entre outros.
#
# Livro indicado pela própria biblioteca:
# <center><img src="figures/livro_pandas.png" align="center" width=100/></center>
#
# Youtube:
#
# - <font color="orange">(Avançado)</font>: [Pandas by <NAME>](https://www.youtube.com/watch?v=UURvPeczxJI&t=3395s) - 19 de agosto de 2021
#

StarcoderdataJupyterScriptsDedupFiltered