<jupyter_start><jupyter_text>![PPGI_UFRJ](imagens/ppgi-ufrj.png) Fundamentos de Ciência de Dados ---[![DOI](https://zenodo.org/badge/335308405.svg)](https://zenodo.org/badge/latestdoi/335308405) --- PPGI/UFRJ 2020.3 Prof <NAME> e <NAME> --- Módulo 2 - Pandas >  **Pandas é a biblioteca de análise de dados em Python**>É uma biblioteca **open source** para análise de dados em Python, de alto desempenho e de fácil uso. Pandas é uma estruturas de dados com eixos rotulados que suportam alinhamento automático ou explícito de dados, evitando erros comuns resultantes de dados desalinhados e do trabalho com dados indexados de forma diferente provenientes de diferentes fontes.>- Possue funcionalidades integradas para lidar com séries temporais.>- Usa as mesmas estruturas de dados para lidar com dados de séries temporais e não temporais.>- Possue operações aritméticas e reduções (como a soma em um eixo) que passariam nos metadados (rótulos dos eixos).>- Tratamento flexível de dados perdidos.>- Merge e outras operações relacionais encontradas em bancos de dados populares (baseados em SQL).>O **kernel** pandas está baseado em duas estruturas de dados primárias nas quais todas as transações, que geralmente são feitas durante a análise de dados são centralizadas em estruturas de **series** e **DataFrames** muito utilizadas em Data Science.  Impotando a biblioteca pandas<jupyter_code># importando a biblioteca
import pandas as pd # pandas
import numpy as np  # numpy<jupyter_output><empty_output><jupyter_text>Series> Uma **série** é um objeto semelhante a uma matriz unidimensional que contém uma matriz de dados de qualquer tipo de dados (NumPy) e uma matriz associada aos rótulos ou indices do dados.<jupyter_code># criando um objeto serie
s0 = pd.Series([4, 7, -5, 3], dtype=np.float64)
s0
# visualizar indices da serie: index
print(s0.index)
# visualiza os valores: values
print(s0.values)
# criando uma serie com indices de letras
indices =['a','b','c','d']
valores = [1,-5, 20, -90]
#
s1 = pd.Series(valores,indices, dtype=np.float32)
s1
# criando uma serie com indices numericos
indices =['1','2','3','4']
valores = [1,-5, 20.0, -90]
#
s1 = pd.Series(valores,indices)
s1
# criando uma serie alaetoria
serie = pd.Series([np.random.randn(50)])
# visualizar a serie
print('Serie:',serie,'Tipo:',type(serie))
# criando uma serie de uma lista
peso_kg = np.linspace(55,80,100)
print(peso_kg)
len(peso_kg)
# convertir dados numpy em Serie (pandas)
pesos = pd.Series(peso_kg)
pesos.head(20)<jupyter_output><empty_output><jupyter_text>Filtrando valores<jupyter_code># fatiar uma serie condicao booleana
p60 =pesos[(pesos>60) & (pesos <70)]
print(p60)
len(p60)
# fatiar uma serie
p10_50= pesos[10:50]
p10_50
# verificar valores nulos "false". Visualiza os 5 valores iniciais (head())
n0 = p10_50.isnull()
n0.head()
# valores não nulos "true"
n1 = p10_50.notnull()
n1.head()<jupyter_output><empty_output><jupyter_text>Selecionando valores internos> Se pode selecionar elementos individuais da mesma forma como é feita nas matrizes numpy, especificando a **chave** (index).<jupyter_code># usando o indice na serie n1
v0 = p10_50[np.random.randint(10,50,1)]
v0
# usando o indice na serie n1 = p10_50[x,y]: x, y:indices
i1 = np.random.randint(10,20,1)
i2 = np.random.randint(21,50,1)
#print(type(i1))
#v1 = pesos[[i1,i2]]
v1 = pesos[[int(i1),int(i2)]]               
v1<jupyter_output><empty_output><jupyter_text>Atribuição de valores aos elementos> A atribuição de novos valores aos elementos da série pode ser feito selecionando o **índice** ou rótulo.<jupyter_code>## atribuir valor -1 al elemento de indice 60
pesos[60] = -1
pesos[[59,60,61]]<jupyter_output><empty_output><jupyter_text>Definir séries a partir de  matrizes NumPy ou de outras séries<jupyter_code># matriz numpy -> valores passados por referencia
m0 = np.array([1,1,2,3,4,5,-1, -1])
S0 = pd.Series(m0)
S0
# os valores da serie são passados por referencia
S0[7] = 10
print(S0)
print(m0)<jupyter_output><empty_output><jupyter_text>Operações e funções matemáticas> Nas séries podem ser usadas todas as operações matemáticas aplicadas nos "arrays" numpy **(+,-,*,/)**.<jupyter_code># usando a serie S0
ds = S0*4 #S0 + 4 # S0 - 2 # S0/4
ds
# usando funções matematicas
l0 = np.log(S0)
l0<jupyter_output><empty_output><jupyter_text>Avaliando valores> A função **unique()** retorna uma matriz com valores únicos, excluindo duplicatas, embora não necessariamente em ordem.> **value_counts()** retorna os valores únicos e conta as ocorrências na série.> **isin()** avalia a pertinência dos elementos na série. Esta função informa se os valores estão contidos na estrutura de dados<jupyter_code># usando unique() em l0
u0 = l0.unique()
print(u0)
# retorna os valores unicos e o numero de ocorrencias deles
u1 = l0.value_counts()
u1
# existem valores 0 na serie?
u2 = l0.isin([0])
u2
# 0 e 3 estão na serie?
u3 = l0.isin([0,3])
u3
# filtra valores usando isin()
u4 = l0[l0.isin([0,3])]
u4<jupyter_output><empty_output><jupyter_text>Operações entre séries<jupyter_code># criando serie 1
mydict1 = {'red': 2000, 'blue': 1000, 'yellow': 500,'orange': 1000}
serie1 = pd.Series(mydict1)
print(serie1)
print()
# serie 2
mydict2 = {'red':400,'yellow':1000,'black':700}
serie2 = pd.Series(mydict2)
print(serie2)
print()
ss = serie1 + serie2
print(ss)<jupyter_output><empty_output><jupyter_text>DataFrames> Um **DataFrame** representa uma estrutura de dados tabular semelhante a uma planilha contendo uma coleção ordenada de colunas, cada uma das quais pode ter um tipo de valor diferente (numérico, string, booleano etc.). O **DataFrame** tem um índice para linha e coluna.<jupyter_code># criando um dataframe: indices = {Idade, Altura,Peso}
df = pd.DataFrame({'Idade':np.random.randint(25,high=50,size=40),
                  'Altura':1.20+np.random.rand(40),
                  'Peso':np.linspace(55,90,40)})
# Visualizar os 5 primeiros registros do dataframe
df.head(20) # 
# algumas metricas sobre os dados
df.describe()<jupyter_output><empty_output><jupyter_text>>  Percentil - divisão da amostra em percetuais.>> - 25% dos elementos são inferiores a X.Y anos, X.Y m e X.Y kg.>> - Metade dos elementos são inferiores a X.Y anos, X.Y m e X.Y kg.>> - 75% dos elementos são inferiores a X.Y anos, X.Y m e X.Y kg.<jupyter_code># visualizar os nomes das colunas
df.columns
# visualizar os valores das colunas
df.values
# Visualizar o DataFrame como Matriz(transposta)
df.T
# "fatiar" um dataframe
idade = df['Idade']
idade.head()
peso =df['Peso']
peso.head()
# fatiar selecionando linhas
df1 = df[(df.Idade > 30) & (df.Idade < 40)]
df1.head()
# operacoes com colulas Peso/Altura
df['peso-altura']= np.round(df['Peso']/df['Altura'],decimals=2)
df.head()<jupyter_output><empty_output><jupyter_text>Leitura de arquivos > Existem funções que permitem ler dados de diversos formatos. Um dos mais usados em **datasets** é o **CSV** - *Comma Separated Value* (Valores Separados por Vírgulas), que podem ser importados e exportados pela maioria de aplicações. | Data          | Formato       | Reader        | Writer        || :---:         | :---:         | :---:         | :---:         || CSV           | Texto         | read_csv      | to_csv        || JSON          | Texto         | read_json     | to_json       || HTML          | Texto         | read_html     | to_html       || MS_EXCEL      | Binário       | read_excel    | to_excel      || SQL           | SQL           | read_sql      | to_sql        |  Google Colab (usar dados do PC)> ```from google.colab import drive```> ```drive.mount('/content/drive')```> Seguir o link para copiar o código e colar o espaço solicitado. **My Drive** é o google drive, logo adicionar o caminho do diretório para fazer a leitura do arquivo desejado.> ```dadosx = pd.read_csv('/content/drive/My Drive/datasets/covid19_confirmed.csv',delimiter=',')```> ```dadosx.head(10)``` >  Importar dados do GitHub> ```!git clone https://github.com/zavaleta/Fundamentos_DS```>  Leitura dos dados> ```file_data = pd.read_csv('Fundamentos_DS/data/file.csv')```  Arquivos CSV<jupyter_code># exemplo 1: Covid19 - Pernambuco
prouni = pd.read_csv('data/cursos-prouni2020.csv',delimiter=',',decimal=',')
prouni.head()
# visualizando as colunas
prouni.columns
# visualizando valores do dataframe
valores = prouni.values
valores<jupyter_output><empty_output><jupyter_text>Selecioando elementos<jupyter_code># visualizando coluna
turno = prouni[['turno','mensalidade']]
turno.head()
# visualizando coluna
campus = prouni['campus_nome']
campus.head()
# visualiza elementos usando o indice da fila
loc_campus = campus.loc[2]
loc_campus
# visualiza elementos usando o 2 indices das filas
loc_campus1 = campus.loc[[2,10]]
loc_campus1
# visualiza elementos usando o indices da fila
loc_campus2 = campus[2:10]
loc_campus2
loc_campus3 = campus.iloc[2:10]
loc_campus3
# eliminar uma coluna
#del dataFrme['nome_coluna']
# turno tem alguma valor nulo?
tn = turno.isnull()
tn.head()<jupyter_output><empty_output><jupyter_text>Arquivos JSON<jupyter_code>read_json = pd.read_json('data/article-prov.json')
print(read_json)
#write_json = pd.to_json('data/file.json')<jupyter_output><empty_output><jupyter_text>Arquivos MS_EXCEL<jupyter_code># criando um arquivo MS_EXCEL
file_excel = prouni.loc[:5,:'mensalidade']
print(file_excel)
# gravando um arquivo excel
file_excel.to_excel('data/excel_teste.xlsx')
read_excel = pd.read_excel('data/excel_teste.xlsx',index_col=0)
read_excel.head()<jupyter_output><empty_output><jupyter_text>Método *iloc*> As linhas de um DataFrame podem ser acessadas por meio do método **iloc**, que usa uma sintaxe semelhante à de uma lista.<jupyter_code># visualiza os dados
prouni.head()
# visualiza a linha = 1
prouni.iloc[1]
# visualiza as linhas 1 ao 4
prouni.iloc[1:4]
# fatiar um data frame
prouni.iloc[:3,:3]
# acessando as filas pares (indices)
pares = prouni.iloc[prouni.index % 2 == 0]
pares.head()<jupyter_output><empty_output><jupyter_text>Método *loc*> **loc** é semelhante ao **iloc**, mas permite indexar um DataFrame por meio de nomes de coluna ou rótulos.<jupyter_code># Visualiza a coluna 1
prouni.loc[0,:'grau']
# fatiar um dataFrame
p0 = prouni.loc[:'grau',:'curso_id']
p0.head()<jupyter_output><empty_output><jupyter_text>Reindexar> O método de reindexação em **Pandas**, significa criar um novo objeto com os dados em concordância com um novo índice.<jupyter_code># pandas original
rein0 = pd.Series([4.5, 7.2, -5.3, 3.6], index=['a', 'b', 'c', 'd'])
rein0
# mudando index
rein1 = pd.Series([4.5, 7.2, -5.3, 3.6], index=['d', 'b', 'a', 'c'])
rein1
# reindexando
r = pd.Series(['blue', 'purple', 'yellow'], index=[0, 2, 6])
rein2 = r.reindex(range(6),method='ffill')
rein2<jupyter_output><empty_output><jupyter_text>Eliminando entradas de uma fila (axis=0) ou coluna (axis=1) - DROP> Eliminar uma ou mais entradas de uma fila/coluna de uma matriz de índice ou de uma lista sem entradas. o método **drop** retornará um novo objeto com o valor indicado ou valores deletados de uma fila/coluna<jupyter_code># criando a serie
d0 = pd.Series(np.arange(5.), index=['a', 'b', 'c', 'd', 'e'])
d0
# drop -> elimiando a fila 'c'
dc = d0.drop('c')
dc
# drop -> elimiando a fila 'c'
d_ae = d0.drop(['a','e'])
d_ae
m4x4 = pd.DataFrame(np.arange(16).reshape((4, 4)),index=['RJ', 'SP', 'AC', 'CE'],
                 columns=['um', 'dois', 'três', 'quatro'])
m4x4
# drop filas (index)
dfil = m4x4.drop(['RJ','CE'])
dfil
# drop coluna (axis=1)
dcol = m4x4.drop('três',axis=1)
dcol
# drop coluna (axis=1)
dcol0 = m4x4.drop('um',axis=1)
dcol0
# drop fila (axis=1)
dfil0 = m4x4.drop('SP',axis=0)
dfil0<jupyter_output><empty_output><jupyter_text>Selecionar<jupyter_code># filtrar por colunas
m1 = m4x4[['um','dois']]
m1<jupyter_output><empty_output><jupyter_text>Filtrar<jupyter_code># filtra elementos > 4
m2 = m4x4[m4x4 > 4]
m2<jupyter_output><empty_output><jupyter_text>Fatiamento (slice)<jupyter_code># slice index
m3 = m4x4['AC':'CE']
m3
# slice index
m4x4['AC':'CE']=5
m4x4<jupyter_output><empty_output><jupyter_text>Tratamentos de falta de dados  >Com frequência é encontrado datasets com falta de dados, com dados nulos ou com dados incoerentes. Estes datasets devem ser limpados e homogeneizados antes de realizar qualquer operação.>Pandas têm duas formas de tratar dados com valores **null**, **NaN** ou **NA**: Usando uma **máscara** que indica perda de valores ou escolher um valor **sentinela** que indica entrada ausente.>1. **Máscara**: A máscara pode ser uma matriz booleana totalmente separada ou pode envolver a representação de um bit para indicar localmente o status nulo de um valor.>2. **Sentinela**: o valor do sentinela pode ser uma convenção específica de dados, como por exemplo, para indicar um valor inteiro com **-999** ou otro valor determinado por convenção. O valor **NaN** é uma convenção da IEEE para determinar um valor de ponto flutuante ausente.   None>É o primeiro valor sentinela usado por Pandas, tratado como um objeto do Python.<jupyter_code># carregando as bibliotecas 
import numpy as np               # numpy
import pandas as pd              # pandas
import matplotlib.pyplot as plt  # graficos
# exemplo
notas_none = np.array([4.0, 7.0, 6.5, None, 10.0, 8.8, None, 9.0, 4.0, 7.0, 9.5])
print('A:',notas_none)
# operção não definida!!!
notas_none.sum()<jupyter_output><empty_output><jupyter_text>NaN>Dados numéricos ausentes. (*Not a Number*). Valor de ponto flutuante especial reconhezidos pelos sistemas que usam a representação padrão de ponto flutuante da IEEE.<jupyter_code>notas_nan = np.array([4.0,7.0, 6.5, np.nan, 10, 8.8, np.nan, 9.0])
print('Notas:',notas_nan)
print('Tipo:',notas_nan.dtype)
# Operacoes aritmeticas: soma
v = 1 + np.nan
v
# Operacoes aritmeticas: multiplicacao
v1 = 0*np.nan
v1
# agregados
notas_nan.sum(), notas_nan.min(), notas_nan.max()<jupyter_output><empty_output><jupyter_text>NaN e None em Pandas<jupyter_code># serie de pandas
serie = pd.Series([2,3.0, np.nan, 8, 5.0, None,-1.0])
serie
# serie de pandas
x_int = pd.Series(range(6), dtype=int)
x_int
x_int[0] = None
x_int[3]  = None
x_int<jupyter_output><empty_output><jupyter_text>Operações com valores nulos> - **isnull()**: Gera uma mácara booleana indicandoi valores ausentes.> - **notnull()**: Retorna os valores não nulos> - **dropna()**: Retorna a serie ou dataframe sem valores nulos.> - **fullna()**: Retorna uma copia dos dados com valores ausentes preenchidos.<jupyter_code># exemplos detectando valores nulos
serie_nulos = pd.Series([-1.0, 1, 4.5, np.nan, 'oi',None, 10])
print('Serie:',serie_nulos)
# valores não nulos
serie_nulos[serie_nulos.notnull()]
# Eliminando valores nulos
n_nulos = serie_nulos.dropna()
n_nulos
# DataFrame
df = pd.DataFrame([[1, np.nan, 2,5],[2, 3, 5, -1.0],[np.nan, 4, 6, 20]])
df
# dropna em dataframe
df1 = df.dropna()
df1
# Elimina colunas
df2 = df.dropna(axis='columns')
df2
# elimina filas ou linhas
df3 = df2 = df.dropna(axis='rows')
df3
# elimina todas as colunas com valores nulos
print(df)
df3 = df.dropna(axis=1)
print(df3)
# preenchendo valores nulos
dados = pd.Series([1, np.nan, 2, None, 3.0, 6.0, 7], index=list('abcdedg'))
dados
# preenchendo com zero
d = dados.fillna(0)
d<jupyter_output><empty_output><jupyter_text>Métodos aritméticos<jupyter_code># criar 2 dataframes
M1 = pd.DataFrame(np.arange(8.).reshape((2, 4)), columns=list('abcd'))
print(M1)
M2 = pd.DataFrame(np.arange(15.).reshape((3, 5)), columns=list('abcde'))
print(M2)
# Método add
M3 = M1 + M2
M3
# Método add - sub - div - mul
M4 = M1.div(M2,fill_value=0)
M4<jupyter_output><empty_output><jupyter_text>Estatísticas descritivas> Os objetos pandas são munidos de um conjunto de métodos matemáticos e estatísticas comuns, estes métodos extraem um único valor de uma série ou de uma série de valores das linhas ou colunas de um DataFrame.> Os métodos estatísticos auxiliam na compreensão e análise do comportamento dos dados.> **sum**, **mean**,**median**,**varience**,**covariance**,**correlation**, etc.<jupyter_code># Gerando dados
df_data =  pd.DataFrame(np.random.randn(10, 5), index = pd.date_range('1/1/2020', periods=10),
                       columns = ['A', 'B', 'C', 'D','E'])
print(df_data)
# soma de  todas as colunas
sc = df_data.sum() # sum(axis=0) # soma cada coluna
print(sc)
# soma cada fila (row)
sc_1 = df_data.sum(axis=1)
print(sc_1)
# media das colunas
media_c = df_data.mean()
print(media_c)
# media das filas
media_f = df_data.mean(axis=1)
print(media_f)
# caluclos usando windows = n: (n+(n-1)+(n-2)=/n) --> n=3 e mean()
print(df_data.rolling(window=3).mean())
# metodos de agregação - rolling
print(df_data)
rol = df_data.rolling(window=3,min_periods=1)
print(rol)
# aggregate todas as collunas
print(rol.aggregate(np.sum))
# coluna A
print(rol['A'].aggregate(np.sum))
#  aggregate multiples colunas
print(rol[['A','B']].aggregate(np.sum))
# aggregate multiples funções a uma coluna
df_group = rol['C'].aggregate([np.sum,np.mean,np.median,np.std])
print(df_group)
# Split data into groups - agrupar
club_data = {'Club': ['Flamengo', 'Inter', 'SP', 'Fluminense', 'Gremio',
   'Flamengo', 'Flamengo', 'Inter', 'Gremio', 'Santos', 'Santos', 'Corinthians'],
   'Rank': [1, 2, 2, 3, 3,4 ,1 ,1,2 , 4,1,2],
   'Ano': [2014,2015,2014,2015,2014,2015,2016,2017,2016,2014,2015,2017],
   'Pontos':[876,789,863,673,741,812,756,788,694,701,804,690]}
df_club = pd.DataFrame(club_data)
print(df_club)
print()
group_ano = df_club.groupby('Ano')    # agrupado por ano
print('Ano:',group_ano.groups)
print()
ag_pontos_anos = group_ano['Pontos'].agg([np.sum, np.mean,np.var,np.std]) # ano e pontos
print(ag_pontos_anos)<jupyter_output><empty_output><jupyter_text>Manipulando bancos de dados> Em muitas aplicações, os dados estão armazenados em formatos ineficientes para guardar grandes volumes de dados. Os bancos de dados relacionais baseados em SQL (como SQL Server, PostgreSQL e MySQL) são amplamente usados nesses casos, e muitos bancos de dados alternativos non-SQL (chamados de NoSQL) se tornaram bastante populares. A escolha do banco de dados geralmente depende das necessidades de desempenho, integridade de dados e escalabilidade de uma aplicação.> O pandas tem algumas funções para simplificar o processo de carregar dados de SQL em um DataFrames.<jupyter_code># Will use an in-memory SQLite database using Python’s built-in sqlite3 driver
import sqlite3
# criar a tabela fcd
query = """
CREATE TABLE fcd
(a VARCHAR(20), b VARCHAR(20), c REAL, d INTEGER);"""
# conexao com o sqlite3
con = sqlite3.connect(':memory:')
con.execute(query)
con.commit()
# inserir dados
data = [('Araruama', '<NAME>', 12.5, 20),
        ('Niterói', 'Nova Iguaçu', 3.6, 15),
        ('Petropolis', 'Teresopolis', 2.0, 10)]
# 
stmt = "INSERT INTO fcd VALUES(?, ?, ?, ?)"
con.executemany(stmt, data)
con.commit()
# retorna as tuplas
cid_0 = con.execute('select * from fcd') # cursor
filas = cid_0.fetchall()
filas
# description
des = cid_0.description
des
pd.DataFrame(filas, columns=list(zip(*cid_0.description))[0])
# leitura do sql em pandas = dataframe
import pandas.io.sql as sql
sql0 = sql.read_sql('select * from fcd', con)
print(sql0)<jupyter_output><empty_output><jupyter_text>Visualização em Pandas<jupyter_code># gerando os valores
df_grafico = pd.DataFrame(np.random.randn(10,5),index=pd.date_range('1/1/2020',
   periods=10), columns=list('ABCDE'))
df_grafico.head()
# visualização do dataframe completo
df_grafico.plot();
# bar plot
df_grafico.plot.bar();
# stacket = True
df_grafico.plot.bar(stacked=True);
# horizontal
df_grafico.plot.barh(stacked=True);
# histogramas
df_grafico.plot.hist(bins=15);
# Box plots
df_grafico.plot.box();
# Area plots (valores positivos)
df_area = pd.DataFrame(np.random.rand(10, 5), columns=['a', 'b', 'c', 'd','e'])
df_area.plot.area();
# scatter plot
df_area.plot.scatter(x='a',y='b');
# Pie chart
df_area.plot.pie(y='a',subplots=True,figsize=(5,5));
# subplots
df_area.plot.pie(subplots=True,figsize=(15,10));<jupyter_output><empty_output><jupyter_text>Grandes volumes de dados<jupyter_code># exemplo 2: dataset - covid19-deaths
#ctotal = pd.read_csv('data/covid-19_casos_full.csv',delimiter=',')
ctotal = pd.read_csv('data/rio_full_casos.csv',delimiter=',')
ctotal.head()
# visualiza o total de registros
print('Total de Registros :> ',len(ctotal))
estado_rj = ctotal[ctotal['state']=='RJ']
estado_rj
# split para rio de janeiro
#casos_rj = pd.DataFrame(estado_rj[estado_rj['city'] == 'Rio de Janeiro'])
#casos_rj.to_csv('data/rio_full_casos.csv')
cidade_rj = estado_rj[estado_rj['city'] == 'Rio de Janeiro']
cidade_rj
# valores para o grafico
y = cidade_rj['new_deaths']
y1 = cidade_rj['new_confirmed']
#print(len(y))
x = np.arange(0,350)
#print(len(x))
import matplotlib.pyplot as plt
#
fig, cov = plt.subplots(nrows=1, figsize=(10, 5))
cov.plot(x,y,'r',linewidth=1.5, label='Mortos')
cov.plot(x,y1,'b',linewidth=1.5, label='Casos confirmados')
cov.legend()
cov.grid()
plt.title('Covid-19 - 18/02/2021')
plt.xlabel('Rio de Janeiro')
plt.ylabel('Total');
# gravando a figura
#fig.savefig('images/conf-mor.png')<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.13900256971542782, 'fraction_numerical': 0.033549062529742074, 'mean_word_length': 5.341279420639711, 'pattern_counts': {'":': 0, '<': 130, '<?xml version=': 0, '>': 189, 'https://': 3, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 1, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '31', 'dir': 'jupyter-structured-clean-dedup', 'id': '207928', 'license': 'CC0-1.0', 'n_tokens_mistral': 8622, 'n_tokens_neox': 8264, 'n_words': 2157, 'path': 'FCD_M2_2_Pandas.ipynb', 'repo_name': 'zavaleta/Fundamentos_DS', 'size': '21031'}