domingo, 9 de agosto de 2020

Banco de dados com pandas

Imagem de CopyrightFreePictures por Pixabay

Já falamos algumas vezes que a biblioteca pandas é ótima para trabalhar com dados estruturados ou tabulares. É comum que grandes empresas usem bancos de dados para guardar dados tabulares ou estruturados. Nesse tutorial, vamos aprender a inserir e ler dados de um banco dados.
Vamos utilizar o SQLite. Este sistema de gerenciamento de banco de dados já está incluído no Python. Por isso não vamos precisar instalar nenhum módulo. Além do SQLite, podemos utilizar python para se conectar com os sistemas de gerenciamentos de banco de dados mais utilizados na atualidade. E podemos utilizar isso com o pandas.

Como utilizar o SQLite do python

Primeiro vamos criar um banco de dados e armazenar informações sobre pessoas aleatórias.

>>> import sqlite3
>>> db = sqlite3.connect('pessoas.db')
>>> cursor = db.cursor()
>>> cursor.execute(
... '''CREATE TABLE pessoas(id INTEGER PRIMARY KEY,
... p_nome TEXT, u_nome TEXT, aniversario INT)'''
... )
<sqlite3.Cursor object at 0x7f7993ce6650>
>>> cursor.execute(
... '''INSERT INTO pessoas VALUES(
... 0, 'Mario', 'Perreira', 1923)'''
... )
<sqlite3.Cursor object at 0x7f7993ce6650>
>>> cursor.execute(
... '''INSERT INTO pessoas VALUES(
... 1, 'Diana', 'Cruz', 1992)'''
... )
<sqlite3.Cursor object at 0x7f7993ce6650>
>>> db.commit()

Agora que já temos o nosso banco de dados vamos passar os dados desse banco de dados para um dataframe pandas. Para ler uma tabela vamos precisar usar o módulo SQLAlchemy. Esse módulo nós ajuda simplificando o processo de obtenção dos dados. O módulo SQLAlchemy não vem instalado com o python mas você pode instalar com o pip: pip install sqlalchemy.

>>> import pandas as pd
>>> import sqlalchemy as sa
>>> engine = sa.create_engine(
... 'sqlite:///pessoas.db', echo=True
... )
>>> conexao_sa = engine.connect()
>>> pessoas = pd.read_sql_table(
... 'pessoas', conexao_sa, index_col='id'
... )
>>> pessoas
   p_nome    u_nome  aniversario
id                              
0   Mario  Perreira         1923
1   Diana      Cruz         1992

Você pode selecionar os dados que quer ler com um consulta SQL. A consulta pode ser feita usando uma conexão SQLite ou SQLAlchemy. Nesse exemplo vamos usar a conexão SQLite do primeiro exemplo:

>>> nome_aniversario = pd.read_sql(sql, db)
>>> nome_aniversario
  p_nome  aniversario
0  Mario         1923
1  Diana         1992

Como funciona...

Nos exemplos desse tutorial, fizemos uso do módulo SQLAlchemy. Essa biblioteca faz a conexão entre o banco de dados SQL. SQLAlchemy pode criar uma conexão com a maioria dos bancos de dados SQL. Com essa conexão podemos criar dataframes a partir de tabelas. E ainda podemos criar um dataframe a partir de uma consulta SQL.

Referência:
Módulo SQLite3
Módulo SQLAlchemy

sexta-feira, 7 de agosto de 2020

Arquivos ZIP com pandas

Imagem de Alexas_Fotos por Pixabay

Já vimos nos tutoriais passados, que os arquivos csv são muito comuns para a criação de datasets. A principal característica dos arquivos csv é que eles são texto puro, sem formatação. Por isso eles podem ficar com um tamanho muito grande. Para tentar resolver esse problema os arquivos csv podem ser compactados. Nesse tutorial vamos aprender a carregar um arquivo csv compactado num arquivo ZIP.
O arquivo csv que vamos utilizar é o único arquivo dentro do arquivo ZIP. Você pode conseguir um arquivo semelhante compactando o arquivo filmes.csv. Nesse tutorial também vamos trabalhar com arquivos ZIP, com vários arquivos csv compactados.
Os arquivos que vamos usar nesse tutorial podem ser baixados gratuitamente aqui.

Como ler arquivos csv compactados

Vamos começar lendo um único arquivo csv compactado. Podemos fazer isso com o método read_csv(). A diferença é a extensão do arquivo que será zip e não csv.

>>> import pandas as pd
>>> animelist = pd.read_csv('AnimeList.zip')
>>> animelist
       anime_id  ...                                       ending_theme
0         11013  ...  ['#1: "Nirvana" by MUCC (eps 1, 11-12)', '#2: ...
1          2104  ...  ['#1: "Ashita e no Hikari (?????)" by Asuka Hi...
2          5262  ...  ['#1: "Rottara Rottara (???? ????)" by Buono! ...
3           721  ...  ['"Watashi No Ai Wa Chiisaikeredo" by Ritsuko ...
4         12365  ...  ['#1: "Pride on Everyday" by Sphere (eps 1-13)...
...         ...  ...                                                ...
14473     26089  ...                                                 []
14474     21525  ...                                                 []
14475     37897  ...                                                 []
14476     34193  ...                                                 []
14477     37908  ...                                                 []

[14478 rows x 31 columns]

Com arquivos compactados, contendo mais de um arquivo csv, a leitura desse arquivo é um pouco mais complicada, comparado com o exemplo anterior. Utilizando o método read_csv() não podemos especificar qual arquivo queremos ler dentro de um arquivo ZIP, mas podemos utilizar o módulo zipfile, que é uma biblioteca padrão do Python, para fazer isso.
Nesse exemplo vamos utilizar um arquivo zip contento mais de um arquivo csv. Você pode usar qualquer arquivo zip contendo arquivos csv.

>>> import pandas as pd
>>> import zipfile
>>> arq_zip = zipfile.ZipFile('dataset.zip')
>>> print('\n'.join(arq_zip.namelist()))
filmes.csv
anime_cleaned.csv
anime_filtered.csv
AnimeList.csv
>>> animeslist = pd.read_csv(arq_zip.open('AnimeList.csv'))
>>> animeslist
       anime_id  ...                                       ending_theme
0         11013  ...  ['#1: "Nirvana" by MUCC (eps 1, 11-12)', '#2: ...
1          2104  ...  ['#1: "Ashita e no Hikari (?????)" by Asuka Hi...
2          5262  ...  ['#1: "Rottara Rottara (???? ????)" by Buono! ...
3           721  ...  ['"Watashi No Ai Wa Chiisaikeredo" by Ritsuko ...
4         12365  ...  ['#1: "Pride on Everyday" by Sphere (eps 1-13)...
...         ...  ...                                                ...
14473     26089  ...                                                 []
14474     21525  ...                                                 []
14475     37897  ...                                                 []
14476     34193  ...                                                 []
14477     37908  ...                                                 []

[14478 rows x 31 columns]

Você pode trabalhar com arquivos compactados do tipo GZIP, XZ e BZ2. O método read_csv() aceita esses tipos de compressão.

Referência:
Método read_csv()
Método ZipFile()

Como ler e criar arquivos do Excel com pandas

Imagem de Esa Riutta por Pixabay

O arquivo CSV é muito comum e utilizado, mas se compararmos esse arquivo com o gigante da Microsoft, o arquivo do Excel, não parece ser grande coisa. Em muitas pesquisas de consultoria, os resultados apontam que o Excel é uma das ferramentas mais críticas em muitas empresas. O Excel é muito utilizado nas empresas para a tomada de muitas decisões importantes.
E por isso a biblioteca pandas fornece métodos para poder manipular esses arquivos. Nesse tutorial vamos aprender como criar e ler arquivos do Excel com a biblioteca pandas.
Antes de continuarmos vamos precisar instalar os pacotes xlwt e openpyxl. Esses pacotes são necessários para podermos exportar o nosso dataframe para um arquivo xls e xlsx. Utilize o pip para instalar os dois pacotes: pip install openpyxl xlwt.

Como ler e criar arquivos do Excel com pandas

O método que vamos utilizar, para criar um arquivo do excel, é o to_excel(). O que precisamos fazer é criar um dataframe e chamar esse método. Veja um exemplo:

>>> import pandas as pd
>>> nome = {'nome':['Fabiana', 'Diana', 'Amanda'],
... 'u_nome':['Ferreira', 'Lima', 'Saturno']}
>>> dataframe = pd.DataFrame(nome)
>>> dataframe.to_excel('dataframe.xls')
>>> dataframe.to_excel('dataframe.xlsx')

Abrindo o arquivo, que acabamos de criar, o resultado deve ser igual a este:

Para ler o arquivo que criamos, e qualquer outro feito no Excel, utilizamos o método read_excel(). Esse método precisa do complemento xlrd. Para baixo use o pip: pip install xlrd.

>>> import pandas as pd
>>> dataframe = pd.read_excel('dataframe.xls')
>>> dataframe
   Unnamed: 0     nome    u_nome
0           0  Fabiana  Ferreira
1           1    Diana      Lima
2           2   Amanda   Saturno

Como o arquivo já tem uma coluna de índice, podemos especificar isso para o método read_excel(), para evitar dados duplicados. Assim não teremos duas colunas de índice.

>>> dataframe = pd.read_excel('dataframe.xlsx', index_col=0)
>>> dataframe
      nome    u_nome
0  Fabiana  Ferreira
1    Diana      Lima
2   Amanda   Saturno

Com esses exemplos aprendemos que podemos ler e criar arquivos do Excel com a biblioteca pandas. Com a instalação de poucos pacotes já podemos manipular o tipo de arquivo mais utilizados pelas empresas.

Referência:
Método DataFrame()
Método to_excel()
Método read_excel()

quinta-feira, 6 de agosto de 2020

Lendo arquivo csv enorme com pandas

Imagem de Tania Dimas por Pixabay

A biblioteca pandas precisa que o computador tenha memoria disponível suficiente para poder funcionar corretamente. Todos os dataframes são alocados na memoria antes de podermos fazer qualquer operação com esses dados. Se você precisar ler os dados de um dataset muito grande, a biblioteca pandas fornece algumas opções. Caso o seu arquivo possa ser processado em partes, você pode ler algumas partes e depois processa-las. Se no seu dispositivo tiver memoria suficiente você pode carregar o arquivo inteiro. Podemos usar algumas dicas para diminuir o tamanho do arquivo.
O recomendado é que o seu computador tenha de três a dez vezes a quantidade de memoria do arquivo que você está trabalhando. Essa memoria extra é usada para manipular esses dados.

Como ler arquivo csv muito grande

Nesse tutorial vamos ler o conjunto o dados filmes.csv. Esse dataset cabe na memória de qualquer computador da atualidade, mas para fins didáticos vamos fazer de conta que não existe memória suficiente. E quando tentamos carregar esse dataset na memória recebemos um erro de falta de memória.
Quando lidamos com arquivos grandes que nossos computadores não tenham memória suficiente precisamos definir o total de memória que o arquivo inteiro vai ocupar. Para essa tarefa vamos usar o parâmetro nrows. Com esse parâmetro definimos a quantidade de linhas que serão carregados na memória.

>>> import pandas as pd
>>> filmes = pd.read_csv('filmes.csv', nrows=1000)
>>> filmes
     indice  codigo_obra  ...     cnpj_requerente data_exibicao
0         0      15639.0  ...  00.568.159/0001-07     06/jul/12
1         1          NaN  ...  03.599.148/0001-82     13/jul/04
2         2      26453.0  ...  02.341.697/0001-90    26/09/2007
3         3          NaN  ...  27.654.722/0001-16    16/12/2002
4         4       4806.0  ...  00.979.601/0001-98     15/jan/03
..      ...          ...  ...                 ...           ...
995     995   18001845.0  ...  00.979.601/0001-98    09/05/2018
996     996   17004586.0  ...  03.599.148/0001-82     19/jul/18
997     997   18002435.0  ...  27.654.722/0001-16     08/jun/18
998     998   17005733.0  ...  06.236.625/0001-33     05/jun/18
999     999   18002628.0  ...  08.346.733/0001-94     04/jul/18

[1000 rows x 9 columns]

Uma coisa importante é saber o quanto de memória um dataframe esta utilizando, e para isso temos o método info(). Esse método fornece algumas informações sobre o dataframe, incluindo a quantidade de memória utilizada.

>>> filmes.info()
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 1000 entries, 0 to 999
Data columns (total 9 columns):
 #   Column                   Non-Null Count  Dtype
---  ------                   --------------  -----
 0   indice                   1000 non-null   int64
 1   codigo_obra              997 non-null    float64
 2   titulo_original          1000 non-null   object
 3   titulo_brasil            1000 non-null   object
 4   ano_producao             999 non-null    float64
 5   diretor                  1000 non-null   object
 6   razao_social_requerente  1000 non-null   object
 7   cnpj_requerente          1000 non-null   object
 8   data_exibicao            1000 non-null   object
dtypes: float64(2), int64(1), object(6)
memory usage: 46.9+ KB

Além das linhas podemos definir quais colunas queremos carregar na memória com o parâmetro usecols.

>>> col = [
... 'diretor',
... 'titulo_original'
... ]
>>> filmes = pd.read_csv('filmes.csv', nrows=1000, usecols=col)
>>> filmes.info()
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 1000 entries, 0 to 999
Data columns (total 2 columns):
 #   Column           Non-Null Count  Dtype
---  ------           --------------  -----
 0   titulo_original  1000 non-null   object
 1   diretor          1000 non-null   object
dtypes: object(2)
memory usage: 7.9+ KB

Selecionando linhas e colunas, conseguimos reduzir o tamanho do dataframe. Com isso podemos reduzir o tamanho de qualquer dataframe.

Referência:
Método read_csv()
Método info()

Criando arquivo csv com pandas

Photo by Maksym Kaharlytskyi on Unsplash

Na internet podemos achar vários arquivos csv. Cada um com tipos deferentes de dados. Esses arquivos têm coisas boas e coisas ruins. A coisa boa é que eles são facilmente lidos por nos humanos, podem ser abertos com um editor de texto simples e podem ser acessados pela maioria dos editores de planilhas. O lado negativo dos arquivos csv é a falta de um padrão para o arquivo. Tem arquivos csv que utilizam vírgula como separador, outros usam ponto e vírgula. Não é possível impor o tipo de dado. Esse tipo de coisa pode tornar a criação desse arquivo complicada.
Nesse tutorial vamos aprender como criar um arquivo csv a partir de um dataframe pandas.
Os dataframes pandas têm métodos que começam com "to_". Os métodos que começam assim são métodos de exportação. Usaremos o método to_csv(). Com ele é possível descarregar um dataframe pandas num arquivo csv.

Como criar um arquivo csv com pandas

Para criar um arquivo csv primeiro precisamos de um dataframe. Nesse exemplo vamos criar um dataframe e depois salvar esse dataframe no HD como um arquivo csv.

>>> import pandas as pd
>>> nome = ['Maria', 'João', 'Daniel', 'Paulo']
>>> idade = [36, 38, 24, 66]
>>> dados = {
... 'nome':nome,
... 'idade':idade
... }
>>> pessoas = pd.DataFrame(dados)
>>> type(pessoas)
<class 'pandas.core.frame.DataFrame'>
>>> pessoas
     nome  idade
0   Maria     36
1    João     38
2  Daniel     24
3   Paulo     66

>>> pessoas.to_csv('pessoas.csv')

Com esse código criamos um dataframe com três colunas, as duas que criamos (nome e idade) e a de índice que é adicionada pelo pandas. Depois salvamos esse dataframe no arquivo pessoas.csv.
Agora com o arquivo criado podemos abri-lo com o método read_csv().

>>> pessoas = pd.read_csv('pessoas.csv')
>>> pessoas
   Unnamed: 0    nome  idade
0           0   Maria     36
1           1    João     38
2           2  Daniel     24
3           3   Paulo     66

Podemos notar que quando salvamos o arquivo com o método to_csv() foi adicionado uma coluna de índice na primeira linha, mas sem nome. E quando abrimos esse arquivo com o método read_csv() é adicionado outra coluna de índice no inicio. Assim ficamos com duas colunas de índice, uma com nome e outra sem (unnamed). Para resolvermos esse problema usamos o parâmetro index_col do método read_csv().

>>> pessoas = pd.read_csv('pessoas.csv', index_col=0)
>>> pessoas
     nome  idade
0   Maria     36
1    João     38
2  Daniel     24
3   Paulo     66

Uma alternativa, para resolver o mesmo problema, é fazer uso do parâmetro index do método to_csv(). Se passarmos o valor False o arquivo não terá um índice.

>>> pessoas = pd.DataFrame(dados)
>>> pessoas.to_csv('pessoas.csv', index=False)
>>> pessoas = pd.read_csv('pessoas.csv')
>>> pessoas
     nome  idade
0   Maria     36
1    João     38
2  Daniel     24
3   Paulo     66

Referência:
Método DataFrame()
Método to_csv()
Método read_csv()

Criando dataframes com pandas

Photo by La-Rel Easter on Unsplash

Podemos criar um dataframe de diversas maneiras e utilizar vários programas pra isso. Nesse tutorial vamos aprender a criar um dataframe com a biblioteca pandas e utilizando a linguagem de programação python.
É comum criar um dataframe a partir de um arquivo existente, ou de um banco de dados. Nos exemplos anteriores sempre criamos o dataframe a partir do arquivo filmes.csv. Nesse tutorial vamos criar um dataframe do zero, sem arquivos pré-existentes ou bancos de dados. Vamos criar um dataframe a partir de algumas listas.

Criando um dataframe pandas

Primeiro vamos criar listas com quatro elementos cada. Essas listas vão ser convertidas em colunas do dataframe, por isso é importante que os elementos das listas sejam homogêneos.

>>> import pandas as pd
>>> nome = ['Bruna', 'Heverton', 'Gelvani', 'Milena']
>>> u_nome = ['Oliveira', 'Ferreira', 'Silva', 'Reis']
>>> nascimento = [1989, 1997, 1988, 1999]

Depois vamos criar um dicionário com os nomes das colunas do dataframe. As chaves (keys) do dicionário serão os nomes das colunas no dataframe.

>>> pessoas = {'nome':nome, 'u_nome':u_nome, 'nascimento':nascimento}

Por fim, criamos o dataframe passando o dicionário pessoa para o método DataFrame().

>>> type(m_dataframe)
<class 'pandas.core.frame.DataFrame>
>>> m_dataframe
       nome    u_nome  nascimento
0     Bruna  Oliveira        1989
1  Heverton  Ferreira        1997
2   Gelvani     Silva        1988
3    Milena      Reis        1999

Nesse exemplo, os elementos das listas foram convertidos em elementos das colunas do nosso dataframe. E as chaves do dicionário pessoas dão nome às colunas do dataframe.
O padrão, quando criamos um dataframe, é o index ser numerado começando do número zero. Podemos mudar isso com o parâmetro index.

>>> m_dataframe = pd.DataFrame(pessoas, index=['a', 'b', 'c', 'd'])
>>> m_dataframe
       nome    u_nome  nascimento
a     Bruna  Oliveira        1989
b  Heverton  Ferreira        1997
c   Gelvani     Silva        1988
d    Milena      Reis        1999

Criando dataframes pandas com dicionários

Também podemos criar um dataframe a partir de uma lista de dicionários.

>>> pd.DataFrame(
... [
... {
... "nome": "Bruna",
... "u_nome": "Oliveira",
... "nascimento": 1989,
... },
... {
... "nome": "Heverton",
... "u_nome": "Ferreira",
... "nascimento": 1997,
... },
... {
... "nome": "Gelvani",
... "u_nome": "Silva",
... "nascimento": 1988,
... },
... {
... "nome": "Milena",
... "u_nome": "Reis",
... "nascimento": 1999,
... },
... ]
... )
       nome    u_nome  nascimento
0     Bruna  Oliveira        1989
1  Heverton  Ferreira        1997
2   Gelvani     Silva        1988
3    Milena      Reis        1999

Nesse exemplo, a ordem das colunas é a mesma das chaves do dicionário. Podemos mudar essa ordem com o parâmetro columns.

>>> pd.DataFrame(
... [
... {
... "nome": "Bruna",
... "u_nome": "Oliveira",
... "nascimento": 1989,
... },
... {
... "nome": "Heverton",
... "u_nome": "Ferreira",
... "nascimento": 1997,
... },
... {
... "nome": "Gelvani",
... "u_nome": "Silva",
... "nascimento": 1988,
... },
... {
... "nome": "Milena",
... "u_nome": "Reis",
... "nascimento": 1999,
... },
... ],
... columns=['nascimento', 'u_nome', 'nome']
... )
   nascimento    u_nome      nome
0        1989  Oliveira     Bruna
1        1997  Ferreira  Heverton
2        1988     Silva   Gelvani
3        1999      Reis    Milena

Mudamos a ordem das colunas passando uma lista com os nomes. A ordem das colunas segue a ordem da lista passada para o parâmetro columns.

Referência:
Método DataFrame()

Inverter a direção de uma operação

Photo by Brendan Church on Unsplash

É comum que alguns métodos dos dataframes pandas tenham o parâmetro eixo. Com esse parâmetro é possível alterar o sentido da operação. Podemos definir o sentido em que a operação deve ocorrer. Os valores passados ao parâmetro podem se 'index' (ou 0) ou 'columns' (ou 1). É muito comum ver o parâmetro de eixo recebendo valores em strings. Isso acontece porque é mais intuitivo. É mais fácil de perceber que a string 'columns' se refere a colunas do que perceber que o número um se refere à mesma coisa.
O valor padrão, da grande maioria dos parâmetros eixo, é o zero (ou 'index'). Por isso o padrão das operações é ir da primeira linha até a última. Nesse tutorial vamos aprender como mudar a direção das operações.

Como inverter a direção de uma operação no dataframe pandas

Vamos começar com um método que já vimos antes, o count(). Esse método conta os elementos não vazios. Por padrão o sentida da operação é o eixo 'index''. Para mudar o sentido da operação usamos o parâmetro axis (eixo).

>>> import pandas as pd
>>> filmes = pd.read_csv('filmes.csv')
>>> filmes.count()
indice                     9262
codigo_obra                9259
titulo_original            9262
titulo_brasil              9262
ano_producao               9259
diretor                    9262
razao_social_requerente    9262
cnpj_requerente            9262
data_exibicao              9262
dtype: int64

>>> filmes.count(axis='columns')
0       9
1       8
2       9
3       8
4       9
       ..
9257    9
9258    9
9259    9
9260    9
9261    9
Length: 9262, dtype: int64

Na primeira chamada, ao método count(), recebemos uma série com o número de elementos não vazios de cada coluna. Isso acontece porque o eixo padrão do método count() é o index. Assim o método count() vai em cada coluna e conta quantos elementos essa coluna tem. Na segunda chamada mudamos o eixo para ‘colunas’. Desse modo o método vai a cada linha e conta quantas colunas não vazias essa linha tem.

Referência:
Método count()
Método read_csv()