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

# +
#tem dois tipos de missing data, o primeiro é quando você faz uma pesquisa e a pessoa não responde uma pergunta
#específica = missing at random
#geralmente o dado que está faltando tem relação com um outro campo do dataset, caso não possua relacionamento
#com algum outro dado, então é chamado de missing completly at random MCAR
# -



import pandas as pd
#o pandas consegue facilmente identificar um dado faltando
#dados faltando geralmente vem no dataset como NaN, Null, NONE ou N/A
#a função read_csv tem um parâmetro chamado na_values que nos deixa especificar o formato dos missing values
#como scalar, strin, lista ou dicionários para serem usados

df = pd.read_csv('resources/week-2/datasets/class_grades.csv')
df.head()

#nós podemos usar a função isnull() para criar uma máscara booleana do DF, isso transmite o isnull
#para todas células
mask = df.isnull()
mask.head()

#isso pode ser util para processar linhas baseadas em certas colunas de dados. outra operação bem útil
#é ser capaz de dropar todas as colunas que estão com dados faltando usando o dropna()
df.dropna().head(10)

# +
#uma outra função util é a fillna() que preenche todos os missing values com um valor dado por nós

df.fillna(0, inplace=True)
df.head(10)

# +
#podemos usar o na_filter para acabar com os espaços em branco, caso ele seja um valor de interesse real.
#em dados sem N/A, passar um na_filter=False pode melhorar a performance de leitura de um arquivo muito grande


# -

df = pd.read_csv('resources/week-2/datasets/log.csv')
df.head(20)

# +
#o método parameter()
#os dois valores fill mais comuns são o ffill (foward) e o bfill(backwards). o fFill preenche a célula com o 
#valor da linha anterior. o bFill é ao contrário, preenche uma célula com o valor da célula seguinte
#note que para que o efeito desejado seja alcançado, o dataset precisa ser colocado em ordem

#no pandas nós podemos organizar pelo index ou valores. aqui vamos promover o timestamp para indexador e então organziar por ele

df = df.set_index('time')
df = df.sort_index()
df.head(20)

# +
#notamos que um só index é compartilhado por mais de um usiário, isso não é o ideal
#agora vamos resetar o index e usar indexação multi-level com o time e user name
#e daí promover o user para um indexador de segundo nível

df = df.reset_index()
df = df.set_index(['time', 'user'])
df.head(20)
# -

#agora que ordedamos o dataset, vamos usar o fill para preencher os dados faltando usando o ffill
df = df.fillna(method='ffill')
df.head(10)

#ainda podemos usar o fill-in para substituir valores com a função replace(). ela permite substituir de várias maneiras:
#value-to-value, lista, dicionário, regex
df = pd.DataFrame({'A': [3, 2, 1, 5, 4],
                   'B': [1, 7, 1, 3, 1],
                   'C': ['a', 'b', 'c', 'd', 'e']})
df.head()

#podemos substituir os 1's com 100's usando o value-to-value
df.replace(1, 7) #olha, substituis os 1's com 100's

# +
#agora vamos tentar pelas listas
#queremos trocar os 1 por 100 e 3 por 300

df.replace([1, 3], [100, 300])
# -

#o replacement também suporta regex
df = pd.read_csv('resources/week-2/datasets/log.csv')
df

# +
#para substituir usando o regex, fazmos o primeiro parametro com o padrão do regex
#que queremos combinar, o segundo parâmetro que desejamos emitir com a combinação
#dai passamos o terceiro parâmetro como regex=True

#queremos aqui capturar tudo que é HTML e substituir por 'webpage'

df.replace(to_replace='.*.html$', value='webpage', regex=True)

#qualquer número de caracteres terminados com html substitui por 'webpage'
# -

# # manipulating a data frame

df = pd.read_csv('resources/week-2/datasets/presidents.csv')
df.head()

#primeiro vamos dividir o nome do presidente em nome/sobrenome
#criando uma cópia da coluna nome
df['Firstname'] = df['President']
df.head()

#agora quebrando a string do nome da coluna Firstname e mantendo só o primeiro nome usando o Regex
df['Firstname'] = df['Firstname'].replace('[ ].*', '', regex = True)
#um espaço em branco, seguido por qualquer caractere, substitui por nada
df.head()

#isso funciona mas tem uma maneira mais fácil e bonitinha de fazer
#vamos dropar a coluna Firstname e fazer de novo usando a função apply()
del(df['Firstname'])


# +
#a função apply() vai pegar uma função arbitrária que escrevemos e aplciá-la na Série ou Dataframe
#em todas as linhas ou colunas
#o que segue é uma função que faz um split numa string usando uma única linha de código

def splitname(row):
    #extraindo o primeiro nome e criando uma nova entrada na Série
    row['Firstname'] = row['President'].split(" ")[0]
    #agora com o último nome
    row['Lastname'] = row['President'].split(" ")[-1]
    #por fim retornamos a row e o pandas vai dar um .apply()
    return row


# -

#e se aplicarmos essa função no DataFrame indicando que queremos faê-lo por colunas
df = df.apply(splitname, axis = 'columns')
df.head()

#tem um outro jeito de fazer o mesmo trabalho usando a função extract()
#vamos dropar essas colunas Firstname/Lastname que criamos e usar esse terceiro método
del(df['Firstname'])
del(df['Lastname'])

# +
#o extract pega uma expressão regular para funcionar e requer que você capture apenas itens que correspondem aos
#grupos que você deseja inserie, como nome e sobrenome

#esse é o padrão para capturar nome e sobrenome, se tiver um nome do meio ele ignora, pega só primeiro e último
pattern="""(^[\w]*)(?:.* )([\w]*$)"""

#a função extract é construida dentro do atributo str da Série objeto, então chamamos ela usando Series.str.extract(pattern)
df['President'].str.extract(pattern).head()

# +
#daí ainda podemos criar nomes para os grupos
# -

pattern="""(?P<Firstname>^[\w]*)(?:.* )(?P<Lastname>[\w]*$)"""
names = df['President'].str.extract(pattern)
names.head()

#daí podemos copiar esses dados para dentro do nosso dataframe original
df['Firstname'] = names['Firstname']
df['Lastname'] = names['Lastname']
df.head()

#agora limpando a  coluna Born, removeremos tudo que não é dia/mês/ano


df['Born'] = df['Born'].str.extract('([\w]{3} [\w]{1,2}, [\w]{4})')
df['Born'].head()

df.head()









StarcoderdataJupyterScriptsDedupFiltered