<SYSTEM_TASK:>
Given the following text description, write Python code to implement the functionality described below step by step
<END_TASK>
<USER_TASK:>
Description:
 Módulo 2
Step9:  Construção
Series
Step20:  DataFrame
Step21:  Acessando valores
Definição das Variáveis
Step22:  Slicing
Series
Step30:  DataFrame
Step33:  * Atribuição de Valores em DataFrames
Step36:  Masks
Conceito
Step38:  Aplicação
* Series
Step41:  * DataFame
Step45:  Operações Vetoriais
Definição das Variáveis
Step46:  Manipulações Numéricas
* Incrementando o Preço Unitário
Step47:  * Desconto de 10% no Preço Unitário
Step48:  * Cálculo do Preço Total por Item
Step49:  * Cálculo do Preço por Kg
Step50:  * Preenchendo NaNs
Step51:  * Soma 
Step52:  * Média
Step53:  * Desvio Padrão
Step54:  * Mediana
Step55:  * Moda (valores mais frequentes)
Step56:  Análise de Dados
Definição das Variáveis
Step61:  Descrição dos dados
Step63:  Desafio 1
Objetivo
Step65:  Dataset Original
O dataset original é uma Series com 1000 elementos cujos dados pertençam a uma distribuição normal de média igual a 150 e desvio padrão 10.
Construção
Step66:  O Acumulador
O acumulador é um DataFrame usado para acumular as transformações feitas em cima do dataset original. Cada transformação será armazenada em uma coluna cujo nome descreve a transformação feita sobre os dados. 
Insira o dataset criado na coluna de nome original.
Step68:  Inserção de dados
Para cada item a seguir, crie um dataset de distribuição normal contendo N elementos, usando a média e o sigma também fornecidos pelo item. 
Em seguida, concatene os novos elementos gerados à Series original usando o código abaixo
Step70:  [ B ]  Elementos de outra distribuição
N = 100
média = 400
sigma = 100
coluna = "outliers_adicionados"
Step72:  [ C ]  Elementos Próximos à média
N = 1000
média = 150
sigma = 0.1
coluna = "elementos_prox_a_media"
Step74:  Avaliação das Séries
Step75:  Desafio 2
Objetivo
Step77:  Dataset Codificado
<ASSISTANT_TASK:>
Python Code:
import numpy as np
import pandas as pd
Explanation: Módulo 2: Introdução à Lib Pandas
Tutorial
Imports para a Aula
End of explanation
 Construtor padrão 
pd.Series(
    name="Compras",
    index=["Leite", "Ovos", "Carne", "Arroz", "Feijão"],  
    data=[2, 12, 1, 5, 2]
)
 Construtor padrão: dados desconhecidos 
pd.Series(
    name="Compras",
    index=["Leite", "Ovos", "Carne", "Arroz", "Feijão"]
)
 Construtor padrão: valor padrão 
pd.Series(
    name="Compras",
    index=["Leite", "Ovos", "Carne", "Arroz", "Feijão"],
    data="fill here"
)
 Recebendo um Dicionário
s = pd.Series({"Leite": 2, "Ovos": 12, "Carne": 1, "Arroz": 5, "Feijão": 2})
s.name = "Compras"
s
 Recebendo uma Lista
s = pd.Series([2, 12, 1, 5, 2])
s
 editando parâmetros
s.name="Compras"
s.index=["Leite", "Ovos", "Carne", "Arroz", "Feijão"]
s
 Ordenação: Índices 
s.sort_index()
 Ordenação: Dados 
s.sort_values(ascending=False)
Explanation: Construção
Series
End of explanation
 Construtor padrão 
pd.DataFrame(
    index=["Leite", "Ovos", "Carne", "Arroz", "Feijão"],
    columns=["quantidade", "unidade"],
    data=[
        [ 2,  "L"],
        [12, "Ud"], 
        [ 1, "Kg"],
        [ 5, "Kg"], 
        [ 2, "Kg"]
    ]
)
 Construtor padrão: dados desconhecidos 
pd.DataFrame(
    index=["Leite", "Ovos", "Carne", "Arroz", "Feijão"],
    columns=["quantidade", "unidade"]
)
 Construtor padrão: valor padrão 
pd.DataFrame(
    index=["Leite", "Ovos", "Carne", "Arroz", "Feijão"],
    columns=["quantidade", "unidade"],
    data="?"
)
 Recebendo um Dicionário
pd.DataFrame(
    {
        "quantidade": {
            "Leite": 2, 
            "Ovos": 12, 
            "Carne": 1, 
            "Arroz": 5, 
            "Feijão": 2
        },
        "unidade": {
            "Leite": "L", 
            "Ovos": "Ud", 
            "Carne": "Kg", 
            "Arroz": "Kg", 
            "Feijão": "Kg"
        }
    }
)
 Recebendo um Dicionário de Series
index = ["Leite", "Ovos", "Carne", "Arroz", "Feijão"]
pd.DataFrame(
    {
        "quantidade": pd.Series(index=index,  data=[2, 12, 1, 5, 2]),
        "unidade": pd.Series(index=index,  data=["L", "Ud", "Kg", "Kg", "Kg"])
    }
)
 Recebendo um vetor de Series
index = ["Leite", "Ovos", "Carne", "Arroz", "Feijão"]
df = pd.DataFrame(
    [
        pd.Series(name="quantidade", index=index,  data=[2, 12, 1, 5, 2]),
        pd.Series(name="unidade", index=index,  data=["L", "Ud", "Kg", "Kg", "Kg"])
    ]
)
df
 Transpondo para ajustar a Tabela 
df = df.T
df
 editando parâmetros
df.index = ["Leite tipo A", "Ovos Orgânicos", "Patinho", "Arroz Arbóreo", "Feijão Preto"]
df.columns = ["Quantidade", "Unidade"]
df
 Ordenação: Índices 
df.sort_index()
 Ordenação: Dados 
df.sort_values(by="Unidade", ascending=False)
Explanation: DataFrame
End of explanation
index = pd.Index(data=["Leite", "Ovos", "Carne", "Arroz", "Feijão"], name="Itens")
index
sq = pd.Series(index=index,  data=[2, 12, 1, 5, 2]).sort_values()
sq
su = pd.Series(index=index,  data=["L", "Ud", "Kg", "Kg", "Kg"]).sort_index()
su
df = pd.DataFrame({"Quantidade": sq, "Unidade": su}).sort_values(by="Unidade")
df
df["Preço p/ Ud"] = [5.00, 29.99, 6.50, 3.30, 0.50]
df["Preço Total"] = [25.00, 29.99, 13.00, 6.60, 6.00]
df
Explanation: Acessando valores
Definição das Variáveis
End of explanation
sq
sq[2]
sq[5:2:-1]
sq["Leite"]
sq["Leite":"Arroz"]
Explanation: Slicing
Series
End of explanation
df
df["Unidade"]
df.Quantidade
 Uma Coluna do DataFrame é uma Series
df["Preço Total"][2]
 Acesso a mais de uma Coluna 
df[["Preço Total", "Quantidade"]]
 acesso às Linhas: método 'loc' 
df.loc["Leite"]
 acesso ao item: método 'loc' 
df.loc["Ovos", "Preço Total"]
 acesso ao item: método 'iloc' 
df.iloc[4, 3]
 acesso por slice: método 'loc' 
df.loc["Leite":, "Preço p/ Ud":]
 acesso por slice: método 'iloc' 
df.iloc[3:, 2:]
Explanation: DataFrame
End of explanation
 Atribuir Valores em 'slices' levanta warnings 
df["Unidade"][[0, 2]] = "Pacote"
df
 Deve-se usar 'loc' ou 'iloc' 
df.loc["Carne", "Unidade"] = "Kilograma"
df.iloc[3, 1] = "Litro"
df
Explanation: * Atribuição de Valores em DataFrames
End of explanation
 mask => array de bool 
sq > 2
 mask => array de bool 
df > 2
Explanation: Masks
Conceito
End of explanation
 atribuição de valores em uma cópia 
s_tmp = sq.copy()
s_tmp
s_tmp[s_tmp == 2]
s_tmp[s_tmp == 2] = 3
s_tmp
Explanation: Aplicação
* Series
End of explanation
 atribuição de valores em uma cópia 
df_tmp = df[["Preço p/ Ud", "Preço Total"]].copy()
df_tmp
 mask 
mask = (df_tmp > 5) & (df_tmp < 10)
mask
df_tmp[mask]
tmp2 = df_tmp.copy()
tmp2[mask] = "?"
tmp2
s_tmp[s_tmp == 2] = 3
s_tmp
Explanation: * DataFame
End of explanation
df = pd.DataFrame(
    index=pd.Index(data=["Leite", "Ovos", "Carne", "Arroz", "Feijão"], name="Itens"),
    columns=["Unidade", "Quantidade",  "Preço Unitário"],
    data=np.array([
        ["Litro", "Dúzia", "Kilograma", "Kilograma", "Kilograma"],
        [4, 3, 1, 5, 2],
        [3.00, 6.50, 25.90, 5.00, 3.80]
    ]).T,
)
df
 verificando dtypes 
df.dtypes
Conversão necessária pois o pandas interp´reta 'mixed types' como strings 
df[["Quantidade",  "Preço Unitário"]] = df[["Quantidade",  "Preço Unitário"]].astype(float)
df
 verificando dtypes 
df.dtypes
Explanation: Operações Vetoriais
Definição das Variáveis
End of explanation
df["Preço Unitário"] += 1.
df
Explanation: Manipulações Numéricas
* Incrementando o Preço Unitário
End of explanation
df["Preço Unitário"] *= 0.90
df
Explanation: * Desconto de 10% no Preço Unitário
End of explanation
df["Preço Total"] = df["Preço Unitário"] * df["Quantidade"]
df
Explanation: * Cálculo do Preço Total por Item
End of explanation
df["Preço Médio Por Kg"] = np.nan
df
mask = df["Unidade"] == "Kilograma"
df[mask]
df.loc[mask, "Preço Médio Por Kg"] = (df.loc[mask, "Preço Unitário"] / df.loc[mask, "Quantidade"]).sum()
df
Explanation: * Cálculo do Preço por Kg
End of explanation
df.fillna(0)
Explanation: * Preenchendo NaNs
End of explanation
df.sum()
Explanation: * Soma : apenas valores numéricos
End of explanation
df.mean()
Explanation: * Média: apenas valores numéricos
End of explanation
df.std()
Explanation: * Desvio Padrão: apenas valores numéricos
End of explanation
df.median()
Explanation: * Mediana: apenas valores numéricos
End of explanation
df.mode()
Explanation: * Moda (valores mais frequentes): todos os tipos de valores
End of explanation
cols=["c1", "c2", "c3", "c4", "c5"]
data = np.random.rand(100, 5) 
data *= np.array([ 10,  20,  30,  40,  50]) 
data += np.array([100, 200, 300, 400, 500])
data = np.ceil(data)
df = pd.DataFrame(columns=cols, data=data)
df.head(10)
Explanation: Análise de Dados
Definição das Variáveis
End of explanation
 descrevendo as distribuições dos dados 
df.describe()
 mesma coisa, manipulando os percentis  
df.describe(percentiles=[0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9])
 Verificando os valores únicos de C3 
df.c3.unique()
 Verificando a frequencia dos valores únicos de C3 
df.c3.value_counts()
Explanation: Descrição dos dados
End of explanation
 Não altere esse valor, pois ele permite que toda a geração aleatória seja igual para todos 
np.random.seed(123456789)
Explanation: Desafio 1
Objetivo:
Analisar como  Outliers deformam um a distribuição normal.
Configurações
End of explanation
 Dataset Original, já criado para a solução 
media = 150
sigma = 10
serie = pd.Series(np.random.randn(1000)) * sigma + media
Explanation: Dataset Original
O dataset original é uma Series com 1000 elementos cujos dados pertençam a uma distribuição normal de média igual a 150 e desvio padrão 10.
Construção: a função np.random.randn é usada para gerar a distribuição normal, para depois transformá-la com a média e o sigma dados.
End of explanation
accum = pd.DataFrame(
    index=range(2600),
    columns=["original"],
    data=serie
)
accum.head().append(accum.tail())
Explanation: O Acumulador
O acumulador é um DataFrame usado para acumular as transformações feitas em cima do dataset original. Cada transformação será armazenada em uma coluna cujo nome descreve a transformação feita sobre os dados. 
Insira o dataset criado na coluna de nome original.
End of explanation
 Escreva a a Solução Aqui 
Explanation: Inserção de dados
Para cada item a seguir, crie um dataset de distribuição normal contendo N elementos, usando a média e o sigma também fornecidos pelo item. 
Em seguida, concatene os novos elementos gerados à Series original usando o código abaixo:
series_original = series_original.append(nova_series).reset_index(drop=True)
Depois disso, insira a Series atualizada no acumulador em uma coluna com o nome de coluna fornecido em cada item.
[ A ]  Elementos da mesma Distribuição
N = 300
média = 150
sigma = 10
coluna = "mesma_distribuição"
End of explanation
 Escreva a a Solução Aqui 
Explanation: [ B ]  Elementos de outra distribuição
N = 100
média = 400
sigma = 100
coluna = "outliers_adicionados"
End of explanation
 Escreva a a Solução Aqui 
Explanation: [ C ]  Elementos Próximos à média
N = 1000
média = 150
sigma = 0.1
coluna = "elementos_prox_a_media"
End of explanation
 Escreva a a Solução Aqui 
Explanation: Avaliação das Séries:
Avaliar o acumulador e verificar o que mudou na distribuição original.
End of explanation
classes = ["Leite", "Ovos", "Carne", "Arroz", "Feijão"]
labels = pd.Series(np.random.choice(classes, 100))
Explanation: Desafio 2
Objetivo:
Implementar o OneHotEncoding, método muito utilizado em Machine Learning para codificar dados categóricos na forma em que algoritmos de aprendizado de máquina compreendam.
Exemplo:
```
original = pd.Series([
    "classe_1",
    "classe_1",
    "classe_2",
    "classe_2",
    "classe_1",
    "classe_2",
])
---
encoded = pd.DataFrame(
    columns=["classe_1", "classe_2"],
    data=[
        [1, 0],
        [1, 0],
        [0, 1],
        [0, 1],
        [1, 0],
        [0, 1]
    ]
)
```
Série Original:
End of explanation
 Escreva a a Solução Aqui 
Explanation: Dataset Codificado:
End of explanation
<END_TASK>