terça-feira, 18 de agosto de 2020

Importando e exportando dados com SQL

Photo by Ken Yam on Unsplash

Até o momento aprendemos a criar um banco de dados, criar uma tabela e inserir dados nessa tabela com a declaração INSERT. O modo que vinhamos fazendo, inserindo linha a linha na tabela, pode ser útil para tabelas de testes rápidos ou adicionar novas linhas numa tabela já existente, mas o mais comum é inserir centenas ou até mesmo milhares de linhas. E fazer isso do jeito que vinhamos fazendo não é viável. Mas não se preocupe, existem outros meios.
Se os seus dados estiverem num arquivo com uma estrutura definida, separado em colunas, como os arquivos CSV, você pode importar esses dados diretamente para uma tabela com a instrução LOAD DATA INFILE. Essa instrução é utilizada para importar dados em massa.
Também podemos utilizar a instrução SELECT INTO OUFILE para exportar os dados de uma tabela. Essa instrução é muito útil quando você quer compartilhar os dados com um colega ou exportar os dados para outro formato, como um arquivo do Excel.
Nesse tutorial vamos aprender como importar e exportar dados utilizando a linguagem SQL. Mas antes de começarmos vamos verificar se a importação de dados é permitida com a instrução SHOW VARIABLES LIKE '%infile%'; e verificar onde o arquivo que vamos importar deve estar, com a instrução SHOW VARIABLES LIKE 'secure_file_priv';.

mysql> SHOW VARIABLES LIKE '%infile%';
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| local_infile  | ON    |
+---------------+-------+
1 row in set (0.01 sec)

mysql> SHOW VARIABLES LIKE 'secure_file_priv';
+------------------+------------------------------------------------+
| Variable_name    | Value                                          |
+------------------+------------------------------------------------+
| secure_file_priv | C:\ProgramData\MySQL\MySQL Server 8.0\Uploads\ |
+------------------+------------------------------------------------+
1 row in set (0.01 sec)

Com essas duas instruções, descobrimos que a importação de arquivos é permitida e a pasta onde devemos colocar o arquivo que vamos importar é a Uploads. Se o valor da variável local_infile for OFF mude o seu valor com a instrução SET GLOBAL local_infile=1;.

Importando dados de um arquivo CSV com SQL

Os arquivos CSV são arquivos de texto puro. Nesses arquivos não existe formatação, os dados, nesse tipo de arquivo, são delimitados por vírgula. Você não precisa de um arquivo com extensão csv, pode ser um simples arquivo txt, mas os dados precisam estar delimitados por vírgulas. Esse é o conteúdo do arquivo que vamos utilizar:

Nome, Idade, Endereco
Amelia, 23, Rua Antonio Monteiro
Rafael, 52, 25 de Marco
Daniel, 32, Teotonio alcantara

Para importar esses dados vamos precisar criar uma tabela com três colunas. Veja o exemplo abaixo:

mysql> CREATE TABLE cadastro
    -> (nome VARCHAR(10), idade SMALLINT, endereco VARCHAR(25));
Query OK, 0 rows affected (0.76 sec)

mysql> LOAD DATA INFILE
    -> 'C:/ProgramData/MySQL/MySQL Server 8.0/Uploads/dados.txt'
    -> INTO TABLE cadastro
    -> FIELDS TERMINATED BY ','
    -> LINES TERMINATED BY '\n'
    -> IGNORE 1 LINES;
Query OK, 3 rows affected (0.16 sec)
Records: 3  Deleted: 0  Skipped: 0  Warnings: 0

mysql> SELECT * FROM cadastro;
+--------+-------+------------------------+
| nome   | idade | endereco               |
+--------+-------+------------------------+
| Amelia |    23 |  Rua Antonio Monteiro  |
| Rafael |    52 |  25 de Marco           |
| Daniel |    32 |  Teotonio alcantara    |
+--------+-------+------------------------+
3 rows in set (0.02 sec)

Como funciona a instrução LOAD DATA INFILE

Na primeira instrução criamos uma tabela com três colunas. Cada uma para guardar strings, números e strings, respectivamente. Repare que esses são os tipos de dados do nosso arquivo dados.txt.
Na primeira linha da segunda instrução, estamos informando que vamos importar um arquivo. Na segunda linha, passamos o caminho desse arquivo entre aspas simples (Repare que não usamos barras invertidas). Depois definimos que os dados estão delimitados por vírgula, a linha termina com uma quebra de linha e que na leitura desse arquivo deve ser ignorado uma linha – a primeira.
Ignoramos uma linha porque, geralmente, a primeira linha dos arquivos csv contêm os nomes das colunas e não os dados.

Exportando uma tabela para um arquivo CSV

Você pode exportar tabelas de um banco de dados para um arquivo CSV com a instrução INTO OUTFILE. Com essa instrução você pode exportar os dados de uma tabela delimitando os valores com qualquer carácter especifico. Veja um exemplo:

mysql> SELECT nome, idade, endereco
    -> INTO OUTFILE 'C:/ProgramData/MySQL/MySQL Server 8.0/Uploads/dados.csv'
    -> FIELDS TERMINATED BY ','
    -> LINES TERMINATED BY '\n'
    -> FROM cadastro;
Query OK, 3 rows affected (0.03 sec)

Como funciona a instrução INTO OUTFILE

Na primeira linha, utilizamos SELECT para selecionar as colunas que queremos exportar. Na segunda linha definimos o caminho do arquivo. Depois definimos que os dados serão delimitados por vírgula, as linhas vão terminar com quebra de linha e, por último, informamos de qual tabela vamos exportar os dados.

domingo, 16 de agosto de 2020

Entendendo tipos de dados do SQL

Photo by travelnow.or.crylater on Unsplash

Quando se procura um banco de dados é bom verificar os tipos de dados em cada em cada tabela e coluna. As vezes o criador do banco de dados disponibiliza um dicionário dos dados. O dicionário é um arquivo que explica os dados do bancos de dados, como os dados foram obtidos, a relação entre eles, a disposição dos dados, e mais. Infelizmente, encontrar um banco de dados com a documentação é muito difícil. Então, o jeito é aprender sobre o banco de dados fazendo inspeções das tabelas e seus dados.
Entender os tipos de dados é uma tarefa importante na analise e criação de bancos de dados. Com os dados armazenados de forma correta a analise e a criação do banco de dados se torna mais precisa. Entender o conceito de tipos de dados pode ser útil além da linguagem SQL, esse é um conceito que pode ser útil em outras linguagens. Os conhecimentos aprendidos nesse tutorial não se aplica apenas a linguagem SQL.
As colunas dos bancos de dados SQL, só podem armazenar um tipo de dado por coluna. Não é possível armazenar dois tipo de de dados na mesma coluna. Quando o tipo de dado é definido com a declaração CREATE TABLE, esse é o único tipo de dado permitido na coluna. A definição do tipo é especifica logo após o nome da coluna. Veja um exemplo:

MariaDB [meu_BD]> CREATE TABLE jogos_brasil(
    -> data_jogo DATE,
    -> gols INTEGER
    -> );

Na tabela jogos_brasil, criamos a coluna data_jogo e definimos que essa coluna vai guardar dados do tipo data adicionando DATE depois do seu nome. Fizemos a mesma coisa com a tabela gols, a diferença é o tipo de dados que essa tabela vai guardar, que é dados do tipo INTEGER (inteiro).
Esses são os tipos de dados mais comuns nos bancos de dados:

  • Caracteres: Qualquer carácter ou simbolo
  • Números: Incluí todos os números
  • Data e hora: Informações de dados e horas

Nesse tutorial vamos aprender a utilizar esses tipos de dados a fundo.

Caracteres

As sequências de caracteres são o tipo de dados mais comum. Isso porque esse tipo pode ser utilizado para guardar dados um conjunto de números, texto ou datas. Mas o dado continua sendo do tipo carácter, '1' e 1 são tipos de dados diferentes. O dado que pode ser guardado no tipo carácter é o '1'. Esses são os tipos de caracteres:

  • CHAR(n) Esse tipo de dado tem um comprimento máximo definido com n. Criando uma coluna com CHAR(25), o tamanho máximo de caracteres que podem ser guardados em cada linha é de vinte caracteres. Se for armazenado menos caracteres o restante será preenchido com espaços em branco. Esse tipo também pode ser escrito na forma longa, CHARACTER(n). A forma mais comum é a curta.
  • VARCHAR(n): Esse tipo de dado é parecido com o anterior, a diferença é que se definirmos o tamanho máximo de 25 caracteres, mas só adicionamos dez caracteres, o restante não será preenchido. Esse tipo de dados é mais utilizado em grandes bancos de dados, porque esse tipo de dado economiza espaço. A sua forma longa é VARYING(n).
  • TEXT: Com esse tipo de dado você pode guardar dados de comprimento ilimitado (A sequência mais longa pode ter o tamanho de até 1GB).

Não a uma diferença de desempenho entre os três tipos de dados. A economia de espaço utilizando os tipos de dados VARCHAR() e TEXT pode ser uma vantagem, mas só em questão de armazenamento. Já que esses tipos de dados vão alocar apenas o espaço necessário.

Números

As colunas do tipo numérico, além de poder guardar dados desse tipo, nos permitem realizar operações matemáticas com esses dados como a soma, multiplicação, divisão entre outros. E nos permite ordenar os dados de forma crescente ou decrescente. Essa é uma vantagem, se a ordem é importante no seu projeto. Por isso, se no seu projeto vai ser preciso fazer operações matemáticas ou precisar de uma ordem, utilize os tipos de dados numéricos.
Esses são os tipos numéricos da linguagem SQL:

  • Inteiros: números inteiros, positivos e negativos
  • Ponto fixo e ponto flutuante: dois formatos de frações de números inteiros

Inteiros

Os dados mais comum nos bancos de dados são os do tipo inteiro. Isso porque os números inteiros estão em toda parte. Olhe ao seu redor e veja quantas coisas podem ser contadas ou medidas com números inteiros.
Existem três tipos de dados do tipo inteiro: smallint, integer e bigint. A diferença entre esses três tipos é o valor máximo que cada tipo pode guardar. Na tabela abaixo, é mostrado a quantidade que cada tipo pode armazenar e a quantidade de memoria utilizada no armazenamento:

Tipo de dado Tamanho em bytes Intervalo
smallint 2 bytes −32768 a +32767
integer 4 bytes −2147483648 a +2147483647
bigint 8 bytes −9223372036854775808 a +9223372036854775807

Uma preocupação ao definir o tipo de dados é o seu consumo de memoria e a escalonabilidade dos dados. Se você escolher um tipo que consome pouca memória e depois esse tipo não conseguir armazenar os seus dados, você terá um problema. Do outro lado é possível que você escolha um tipo que consome mais memoria e nunca venha a precisar dessa precisão extra. Por isso faça um estudo pra definir qual tipo usar.

Tipos de ponto flutuante

Existem dois tipos de de dados de ponto flutuante, real e de precisão dupla. a diferença entre os dois é a quantidade de dados que eles podem representar. O tipo real tem precisão de seis casas decimais e o de precisão dupla quinze. Veja uma lista dos tipos de ponto flutuante:

Tipo de dado Tamanho em bytes Intervalo
numeric, decimal Variável Até 131072 dígitos antes da vírgula decimal;
Até 16383 dígitos após o ponto decimal
real 4 bytes Precisão de até 6 casas decimais
double precision 8 bytes Precisão de até 15 casas decimais

Veja um exemplo de como utilizar cada tipo de ponto flutuante:

MariaDB [meu_BD]> CREATE TABLE tipos_numericos(
    -> coluna_numeric NUMERIC(20, 5),
    -> coluna_real REAL,
    -> coluna_d_precisao DOUBLE PRECISION
    -> );
Query OK, 0 rows affected (0.021 sec)

MariaDB [meu_BD]> INSERT INTO tipos_numericos
    -> VALUES
    -> (.8, .8, .8),
    -> (3.13579, 3.13579, 3.13579),
    -> (2.1234469287, 2.1234469287, 2.1234469287);
Query OK, 3 rows affected, 1 warning (0.006 sec)
Records: 3  Duplicates: 0  Warnings: 1

MariaDB [meu_BD]> SELECT * FROM tipos_numericos;
+----------------+--------------+-------------------+
| coluna_numeric | coluna_real  | coluna_d_precisao |
+----------------+--------------+-------------------+
|        0.80000 |          0.8 |               0.8 |
|        3.13579 |      3.13579 |           3.13579 |
|        2.12345 | 2.1234469287 |      2.1234469287 |
+----------------+--------------+-------------------+
3 rows in set (0.001 sec)

Note que os dois último números da coluna coluna_numeric foram arredondados e o primeiro foi preenchido com zeros. Isso acontece porque definimos a precisão de cinco casas decimais. Assim, se o número não tiver precisão suficiente as casas decimais serão preenchidas com zeros. E se passar do número especificado, o número é arredondado.

Escolhendo o tipo de dados numérico

Definir qual tipo de dados usar é uma tarefa que demanda estudo e depende de cada caso, mas existem alguma dicas que podem ser útil na escolha:

  1. Sempre que possível utilize números inteiros. Só use tipos de ponto flutuante se for necessário.
  2. Se precisar utilizar dados de ponto flutuante e precisar de exatidão no cálculos utilize o NUMERIC ou se equivalente DECIMAL.
  3. Escolha um tipo de dado grande o suficiente. Só use um tipo de dado menor quando você tiver certeza que não vai precisar de um número maior.

Data e hora

Quando você digita uma data em um formulário de pesquisa, você está obtendo os benefícios dos bancos de dados terem conhecimento da hora atual, além da capacidade de suportar os formatos de datas, horas e as variedades do calendário, como os anos bissextos e fusos horários. Isso é crucial para narrar histórias com dados, porque a questão de quando algo ocorreu normalmente é uma questão tão importante quanto quem, o quê ou quantos estavam participando da historia.
Veja uma lista dos tipos de dados de data e hora mais usados:

Tipo de dado Tamanho em bytes Descrição Intervalo
timestamp 8 bytes Data e hora 4713 AC to 294276 DC
date 4 bytes Data 4713 AC to 5874897 DC
time 8 bytes Hora 00:00:00 to 24:00:00

Veja um exemplo de como utilizar esses tipos de dados:

MariaDB [meu_BD]> CREATE TABLE data_hora(
    -> coluna_timestamp TIMESTAMP,
    -> coluna_data DATE,
    -> coluna_time TIME
    -> );
Query OK, 0 rows affected (0.021 sec)

MariaDB [meu_BD]> INSERT INTO data_hora
    -> VALUES
    -> ('2018-12-31 01:00', '2018-04-23', '12:00:21'),
    -> ('2012-06-29 02:00', '2019-04-23', '14:30:22'),
    -> (now(), '2018-04-23', '12:00:21');

Query OK, 3 rows affected (0.003 sec)

A função now() retorna a data e hora de quando a função é chamada. Se for passado uma data errada isso vai gerar um erro. Um exemplo de data errada é: '2018-02-30'.

sábado, 15 de agosto de 2020

Exploração de dados com SELECT

Photo by Edu Grande on Unsplash

A melhor parte de analisar os dados é quando vou entrevistar os dados (obter informações). É nessa etapa que descobrimos se os dados estão completos, se existe algum dado que não é necessário e, acima de tudo, que tipo de informações podemos obter com esses dados. Uma maneira de pensar nessa etapa é como se ela você uma entrevista de emprego. Você deve fazer perguntas que vão lhe dar as informações para contratar essa pessoa e onde ela será mais produtiva. Do mesmo modo você deve fazer com os dados: Esses dados me serão útil? Onde?
A entrevista é importante porque você obtém informações. Por exemplo, numa entrevista de emprego você descobre que metade dos entrevistados não colocou o nome do pai ou não informou um endereço de e-mail. Na entrevista você pode descobrir se os seus dados estão incorretos: nomes trocados, faltando letras, data no formato errado, entre outras coisas. Esse tipo de informação se torna parte dos dados.
Na linguagem SQL, começamos a entrevista com a declaração SELECT. Essa declaração é utilizada para recuperar informações de linhas e colunas nos bancos de dados. A instrução SELECT pode ser simples, retornando toda a informação sem nenhum filtro, ou pode ser complexa, retornando dezenas de tabelas e aplicando filtros e cálculos.
Nesse tutorial vamos começar com instruções SELECT simples.

Sintaxe básica da declaração SELECT

Nesse exemplo, vamos selecionar todas as linhas e colunas da tabela funcionarios. Essa coluna está no banco de dados que criamos no último tutorial. É importante ter um banco de dados selecionado antes de clamar a instrução SELECT. Você pode notar o banco de dados selecionado entre colchetes.

MariaDB [(none)]> USE meu_banco_de_dados;
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A

Database changed
MariaDB [meu_banco_de_dados]> SELECT * FROM funcionarios;
+------+---------+----------+-------------------+-------------+---------+
| id   | p_nome  | u_nome   | profissao         | data_inicio | salario |
+------+---------+----------+-------------------+-------------+---------+
|    0 | Eveline | Ferreira | Vendedor          | 2018-02-03  |    3400 |
|    1 | Osvaldo | Perreira | Vendedor          | 2018-03-03  |    3400 |
|    2 | Maria   | Saturno  | Gerente de vendas | 2018-01-01  |    8500 |
|    3 | Mariana | Reis     | Diretor           | 2018-01-01  |    5000 |
|    4 | Marisa  | Lima     | Gerente           | 2019-03-01  |    9000 |
+------+---------+----------+-------------------+-------------+---------+
5 rows in set (0.001 sec)

Esse exemplo mostra a forma mais básica de selecionar dados com a linguagem SQL. Utilizamos o asterisco, depois da declaração SELECT, como um curinga. O curinga é utilizado no lugar de um valor especifico. O asterisco assume o valor de todos os valores possíveis. A instrução utilizada nesse exemplo é uma forma de dizer: 'selecione todas as colunas da tabela funcionarios'. Se você passar o nome de uma coluna, no lugar do asterisco, apenas os valores dessa coluna serão apresentados. A declaração FROM indica onde a declaração SELECT deve procurar os dados. O ponto e vírgula é utilizado para sinalizar o fim da instrução.

Consultando um conjunto de colunas

O asterisco é utilizado para descobrir todo o conteúdo de uma tabela. Com grandes bancos de dados é mais prático limitar o número de coluna que a declaração deve retornar. Você pode não ter interesse nos dados sobre id ou data de entrada, você pode estar procurando informações sobre profissão e salário. Podemos definir os dados que temos interesse passando os nomes das colunas separados por vírgula depois da declaração SELECT. Veja um exemplo:

MariaDB [meu_banco_de_dados]> SELECT salario, profissao, p_nome FROM funcionarios;
+---------+-------------------+---------+
| salario | profissao         | p_nome  |
+---------+-------------------+---------+
|    3400 | Vendedor          | Eveline |
|    3400 | Vendedor          | Osvaldo |
|    8500 | Gerente de vendas | Maria   |
|    5000 | Diretor           | Mariana |
|    9000 | Gerente           | Marisa  |
+---------+-------------------+---------+
5 rows in set (0.001 sec)

Note que os dados foram retornados na ordem em que passamos os nomes das colunas. Primeiro o salário, depois a profissão e por último o nome.
Mesmos esses exemplos básicos, mostram uma boa estrategia para iniciar a analise de dados. É uma prática comum verificar se todos os dados estão presentes e no formato certo. As datas estão completas? Dia, mês e ano? Ou só o mês e o ano? Existem nomes começando, misteriosamente, com a letra C? Esses são alguns problemas que você pode achar nessa "entrevista".
Nesse exemplo, utilizamos um banco de dados com poucas linhas, mas quando você se deparar com um banco de dados, com centenas ou milhares de linhas, é preciso fazer uma analise rápida da quantidade e qualidade dos dados. Vamos fazer isso com mais algumas declarações do SQL.

Selecionando valores únicos com a declaração DISTINCT

É muito comum encontrar colunas com valores duplicados. Na coluna profissao temos algumas linhas com o valor vendedor. Isso porque uma empresa pode ter vários vendedores. Se você precisar saber quais profissões estão presentes na tabela profissao, podemos fazer uma consulta que vai retornar apenas valores únicos, eliminando os valores duplicados com a declaração DISTINCT (os valores não serão mostrados, mais continuam na tabela).

MariaDB [meu_banco_de_dados]> SELECT DISTINCT profissao
    -> FROM funcionarios;
+-------------------+
| profissao         |
+-------------------+
| Vendedor          |
| Gerente de vendas |
| Diretor           |
| Gerente           |
+-------------------+
4 rows in set (0.001 sec)

Mesmo a tabela funcionarios tendo cinco linhas, essa instrução nos mostro apenas quatro. Isso porque o valor Vendedor aparece mais de uma vez e a declaração DISTINCT nos mostra apenas valores únicos. Essa declaração é útil para analisar a quantidade e a qualidade dos dados. Com ela podemos saber o quanto de dados vamos analisar e quantos desses dados estão numa boa qualidade. Por exemplo, com a declaração DISTINCT podemos saber se existem dados escrito de forma de forma errada, como o valor Vendedor escrito dessa forma: Cendedor.
Podemos ver os valores únicos de mais de uma coluna por vez. Para isso precisamos passar os nomes das colunas separadas por vírgula.

MariaDB [meu_banco_de_dados]> SELECT DISTINCT profissao, salario
    -> FROM funcionarios;
+-------------------+---------+
| profissao         | salario |
+-------------------+---------+
| Vendedor          |    3400 |
| Gerente de vendas |    8500 |
| Diretor           |    5000 |
| Gerente           |    9000 |
+-------------------+---------+
4 rows in set (0.001 sec)

Desse modo podemos saber, por exemplo, quantos profissões tem salários diferentes. Se tiver uma pessoa que tem a mesma profissão, mas que recebe um salário diferente, será retornado o valor profissão para cada salário diferente.
Adicione uma nova linha na tabela funcionarios com o valor Vendedor e com um salário diferente de 3400 (Veja como fazer isso no tutorial anterior). Depois chame a mesma instrução do exemplo acima, o resultado deve ser parecido com esse:

MariaDB [meu_banco_de_dados]> SELECT DISTINCT profissao, salario
    -> from funcionarios;
+-------------------+---------+
| profissao         | salario |
+-------------------+---------+
| Vendedor          |    3400 |
| Gerente de vendas |    8500 |
| Diretor           |    5000 |
| Gerente           |    9000 |
| Vendedor          |    6500 |
+-------------------+---------+
5 rows in set (0.001 sec)

Note que agora temos dois valores Vendedor na coluna profissão, mas com os valores da coluna salário diferentes.

Ordenando dados com a declaração ORDER BY

Um maneira de encontrar algum sentido nos dados é organizando esses dados de alguma forma. Quando os dados estão organizados fica mais fácil encontrar algum padrão que não percebemos quando os dados estão misturados. Com a linguagem SQL podemos organizar os dados de uma consulta com a declaração ORDER BY seguido do nome da coluna ou das colunas.
Quando utilizamos ORDER BY numa consulta não estamos modificando a tabela, apenas os dados retornados pela consulta. Veja um exemplo de como utilizar ORDER BY:

MariaDB [meu_banco_de_dados]> SELECT p_nome, profissao, salario
    -> FROM funcionarios
    -> ORDER BY salario DESC;
+---------+-------------------+---------+
| p_nome  | profissao         | salario |
+---------+-------------------+---------+
| Marisa  | Gerente           |    9000 |
| Maria   | Gerente de vendas |    8500 |
| Fabiana | Vendedor          |    6500 |
| Mariana | Diretor           |    5000 |
| Eveline | Vendedor          |    3400 |
| Osvaldo | Vendedor          |    3400 |
+---------+-------------------+---------+
6 rows in set (0.001 sec)

Nesse exemplo, organizamos os dados de forma decrescente adicionando a palavra-chave DESC. Por padrão ORDER BY organiza os dados de forma crescente. Ordenando os valores de forma decrescente descobrimos qual é a profissão que ganha mais.
A organização nos permite fazer consultas de forma mais direta e uma maior flexibilização na hora de visualizar os dados. Um dessas flexibilidades é a capacidade de organizar mais de uma coluna.

MariaDB [meu_banco_de_dados]> SELECT p_nome, profissao, data_inicio
    -> FROM funcionarios
    -> ORDER BY p_nome ASC, data_inicio DESC;
+---------+-------------------+-------------+
| p_nome  | profissao         | data_inicio |
+---------+-------------------+-------------+
| Eveline | Vendedor          | 2018-02-03  |
| Fabiana | Vendedor          | 2019-03-20  |
| Maria   | Gerente de vendas | 2018-01-01  |
| Mariana | Diretor           | 2018-01-01  |
| Marisa  | Gerente           | 2019-03-01  |
| Osvaldo | Vendedor          | 2018-03-03  |
+---------+-------------------+-------------+
6 rows in set (0.001 sec)

Nesse exemplo, organizamos a coluna p_nome de forma crescente (ordem alfabética) e, a coluna data_inicio, de forma decrescente. Mas se a coluna data_inicio esta organizada de forma decrescente porque a data 2019-03-20 não está no topo? Porque a prioridade é a coluna p_nome. Primeiro os resultados são organizados por nomes e depois por data, criando subgrupos de organização.
Com esse exemplo, podemos obter a resposta para o tipo de pergunta: “Qual é a pessoa, que o nome começa com F, que está na empresa a mais tempo?”. Esse é um exemplo bobo, mas com os dados certos essa informação é muito importante.

Filtrando linhas com WHERE

Com um banco de dados grande você vai precisar limitar os resultados de uma consulta. Talvez você queira apenas os resultados que satisfaça algumas condições. Por exemplo, as profissões que ganham mais de três mil ou o nome das pessoas que trabalham como vendedor. Para limitar os resultados com condições que os dados devem ter usamos a declaração WHERE.
A declaração WHERE é utilizada para encontrar dados que correspondam a um valor especifico ou satisfação uma condição. Utilizando WHERE você pode excluir linhas com base em condições.
A declaração WHERE vem depois da declaração FROM e do nome da tabela onde vamos fazer uma consulta. Veja um exemplo:

MariaDB [meu_banco_de_dados]> SELECT p_nome, profissao, salario
    -> FROM funcionarios
    -> WHERE profissao = 'Vendedor';
+---------+-----------+---------+
| p_nome  | profissao | salario |
+---------+-----------+---------+
| Eveline | Vendedor  |    3400 |
| Osvaldo | Vendedor  |    3400 |
| Fabiana | Vendedor  |    6500 |
+---------+-----------+---------+
3 rows in set (0.003 sec)

Nesse exemplo, fizemos uma consulta nas colunas p_nome, profissao e salario da tabela funcionarios e definimos que queremos ver apenas as linhas onde o valor da coluna profissao é igual a Vendedor. No exemplo acima, utilizamos apenas o operador igual, mas a linguagem SQL tem suporte a outros operadores. Veja a lista dos operadores suportados pela linguagem SQL:

Operador Função Exemplo
= Igual WHERE profissao = ‘Vendedor’
<> Diferente WHERE profissao <> ‘Vendedor’
> Maior que WHERE salario > 3000
< Menor que WHERE salario < 6000
>= Maior ou igual WHERE salario >= 6500
<= Menor ou igual WHERE salario <= 6500
BETWEEN Entre x e y WHERE salario BETWEEN 6000 AND 9000
IN Corresponde a um dos elementos passados WHERE profissao IN (‘Vendedor’, 'Gerente de vendas')
LIKE Corresponde a um padrão (Case sensitive) WHERE p_nome LIKE ‘Mar%’
NOT Nega uma condição WHERE p_nome NOT ILIKE ‘mar%’

Agora que já sabemos quais operadores podemos usar, vamos utilizar cada operador num exemplo. Vamos começar com o operador igual. Vamos selecionar todas as linhas com o valor da coluna salario igual a 3400.

MariaDB [meu_banco_de_dados]> SELECT u_nome, profissao, salario
    -> FROM funcionarios
    -> WHERE salario = 3400;
+----------+-----------+---------+
| u_nome   | profissao | salario |
+----------+-----------+---------+
| Ferreira | Vendedor  |    3400 |
| Perreira | Vendedor  |    3400 |
+----------+-----------+---------+
2 rows in set (0.001 sec)

Para o nosso próximo exemplo, vamos selecionar todas as linhas que tenham um valor diferente de Vendedor na coluna profissao.

MariaDB [meu_banco_de_dados]> SELECT p_nome, profissao, salario
    -> FROM funcionarios
    -> WHERE profissao <> 'Vendedor';
+---------+-------------------+---------+
| p_nome  | profissao         | salario |
+---------+-------------------+---------+
| Maria   | Gerente de vendas |    8500 |
| Mariana | Diretor           |    5000 |
| Marisa  | Gerente           |    9000 |
+---------+-------------------+---------+
3 rows in set (0.001 sec)

No exemplo abaixo, vamos usar os operadores >, <, >=, <=.

MariaDB [meu_banco_de_dados]> SELECT p_nome, profissao, salario
    -> FROM funcionarios
    -> WHERE salario > 4000;
+---------+-------------------+---------+
| p_nome  | profissao         | salario |
+---------+-------------------+---------+
| Maria   | Gerente de vendas |    8500 |
| Mariana | Diretor           |    5000 |
| Marisa  | Gerente           |    9000 |
| Fabiana | Vendedor          |    6500 |
+---------+-------------------+---------+
4 rows in set (0.001 sec)

MariaDB [meu_banco_de_dados]> SELECT p_nome, profissao, salario
    -> FROM funcionarios
    -> WHERE salario < 7000;
+---------+-----------+---------+
| p_nome  | profissao | salario |
+---------+-----------+---------+
| Eveline | Vendedor  |    3400 |
| Osvaldo | Vendedor  |    3400 |
| Mariana | Diretor   |    5000 |
| Fabiana | Vendedor  |    6500 |
+---------+-----------+---------+
4 rows in set (0.001 sec)

MariaDB [meu_banco_de_dados]> SELECT p_nome, profissao, salario
    -> FROM funcionarios
    -> WHERE salario >= 3400;
+---------+-------------------+---------+
| p_nome  | profissao         | salario |
+---------+-------------------+---------+
| Eveline | Vendedor          |    3400 |
| Osvaldo | Vendedor          |    3400 |
| Maria   | Gerente de vendas |    8500 |
| Mariana | Diretor           |    5000 |
| Marisa  | Gerente           |    9000 |
| Fabiana | Vendedor          |    6500 |
+---------+-------------------+---------+
6 rows in set (0.001 sec)

MariaDB [meu_banco_de_dados]> SELECT p_nome, profissao, salario
    -> FROM funcionarios
    -> WHERE salario <= 9000;
+---------+-------------------+---------+
| p_nome  | profissao         | salario |
+---------+-------------------+---------+
| Eveline | Vendedor          |    3400 |
| Osvaldo | Vendedor          |    3400 |
| Maria   | Gerente de vendas |    8500 |
| Mariana | Diretor           |    5000 |
| Marisa  | Gerente           |    9000 |
| Fabiana | Vendedor          |    6500 |
+---------+-------------------+---------+
6 rows in set (0.001 sec)

Para o nosso próximo exemplo vamos selecionar todas as linhas que o valor da coluna salario esteja entre 3500 e 8900.

MariaDB [meu_banco_de_dados]> SELECT p_nome, profissao, salario
    -> FROM funcionarios
    -> WHERE salario BETWEEN 3500 AND 8900;
+---------+-------------------+---------+
| p_nome  | profissao         | salario |
+---------+-------------------+---------+
| Maria   | Gerente de vendas |    8500 |
| Mariana | Diretor           |    5000 |
| Fabiana | Vendedor          |    6500 |
+---------+-------------------+---------+
3 rows in set (0.004 sec)

Com operador IN você pode passar um conjunto de valores para a declaração WHERE. Desse modo a declaração WHERE vai fazer mais de uma verificação por dado. Por exemplo, você pode querer selecionar as linhas que tenham os valores 'Vendedor' ou 'Gerente' na coluna profissao. Veja o exemplo disso:

MariaDB [meu_banco_de_dados]> SELECT p_nome, profissao, salario
    -> FROM funcionarios
    -> WHERE profissao IN ('Gerente', 'Vendedor');
+---------+-----------+---------+
| p_nome  | profissao | salario |
+---------+-----------+---------+
| Eveline | Vendedor  |    3400 |
| Osvaldo | Vendedor  |    3400 |
| Marisa  | Gerente   |    9000 |
| Fabiana | Vendedor  |    6500 |
+---------+-----------+---------+
4 rows in set (0.001 sec)

Usando o operador LIKE

Para o nosso próximo exemplo vamos utilizar o operador LIKE. Esse operador vai selecionar dados que começam com a string que passamos para o operador. É importante notar que o operador LIKE diferencia letras maiúsculas de minusculas, então Mar e mar são diferentes.

MariaDB [meu_banco_de_dados]> SELECT p_nome, profissao, salario
    -> FROM funcionarios
    -> WHERE p_nome LIKE 'Mar%';
+---------+-------------------+---------+
| p_nome  | profissao         | salario |
+---------+-------------------+---------+
| Maria   | Gerente de vendas |    8500 |
| Mariana | Diretor           |    5000 |
| Marisa  | Gerente           |    9000 |
+---------+-------------------+---------+
3 rows in set (0.001 sec)

O sinal de porcentagem (%) no final da string é utilizado para sinalizar que queremos qualquer valor que comece com 'Mar' não importa o tamanho que esse valor tenha. Esse caractere também pode ser utilizado para selecionar valores com um final de string em comum. Por exemplo, na coluna p_nome existem dois nomes que terminam com ‘ana’ no final, Fabiana e Mariana. Para selecionar as linhas que tenham esses valores passaríamos a string ‘%ana’ para o operador LIKE.
Outro carácter utilizado é o underline (_). Esse caractere é usado para sinalizar que queremos os valores com apenas um carácter a mais dos que já passamos. Por exemplo, passando ‘Marian_’ para o operador LIKE, o operador vai retornar todos os valores que comecem com ‘Marian’ e tenham um carácter a mais. Esse carácter pode ser qualquer um, pode ser um a, um b ou c. Se começar com ‘Marian’ e tiver somente mais um carácter o valor será selecionado pelo operador. E o underline pode ser usado no meio da palavra.
Veja outros exemplos de utilização dos caracteres de porcentagem e underline:

MariaDB [meu_banco_de_dados]> SELECT p_nome, profissao, salario
    -> FROM funcionarios
    -> WHERE p_nome LIKE '%ana';
+---------+-----------+---------+
| p_nome  | profissao | salario |
+---------+-----------+---------+
| Mariana | Diretor   |    5000 |
| Fabiana | Vendedor  |    6500 |
+---------+-----------+---------+
2 rows in set (0.000 sec)

MariaDB [meu_banco_de_dados]> SELECT p_nome, profissao, salario
    -> FROM funcionarios
    -> WHERE p_nome LIKE '%ia%';
+---------+-------------------+---------+
| p_nome  | profissao         | salario |
+---------+-------------------+---------+
| Maria   | Gerente de vendas |    8500 |
| Mariana | Diretor           |    5000 |
| Fabiana | Vendedor          |    6500 |
+---------+-------------------+---------+
3 rows in set (0.001 sec)

MariaDB [meu_banco_de_dados]> SELECT p_nome, profissao, salario
    -> FROM funcionarios
    -> WHERE p_nome LIKE 'Marian_';
+---------+-----------+---------+
| p_nome  | profissao | salario |
+---------+-----------+---------+
| Mariana | Diretor   |    5000 |
+---------+-----------+---------+
1 row in set (0.001 sec)

MariaDB [meu_banco_de_dados]> SELECT p_nome, profissao, salario
    -> FROM funcionarios
    -> WHERE p_nome LIKE 'Mar_ana';
+---------+-----------+---------+
| p_nome  | profissao | salario |
+---------+-----------+---------+
| Mariana | Diretor   |    5000 |
+---------+-----------+---------+
1 row in set (0.001 sec)

Combinando operadores com AND ou OR

A linguagem SQL nos permite utilizar mais de um operador ao mesmo tempo. Assim podemos definir mais de uma condição para selecionar um valor. Por exemplo, você pode querer selecionar apenas os valores que tenham o valor 'Vendedor' na coluna profissao e o valor da coluna salario maior que 3400. Para isso usamos a palavra chave AND. Com ela o dado só será selecionado se atender as duas condições, ter o valor ‘Vendedor’ na coluna profissao E (AND) o valor da coluna salario maior que 3400.
A palavra-chave OR define duas condições e se qualquer uma dessas condições for satisfeita o dado é selecionado. Por exemplo, se você quiser selecionar os dados que tenham o valor ‘Vendedor’ na coluna profissao ou o valor da coluna salario seja maior que 3000, você deve usar OR.
Veja exemplos de como utilizar AND e OR:

MariaDB [meu_banco_de_dados]> SELECT p_nome, profissao, salario
    -> FROM funcionarios
    -> WHERE profissao = 'Vendedor'
    -> AND salario > 3400;
+---------+-----------+---------+
| p_nome  | profissao | salario |
+---------+-----------+---------+
| Fabiana | Vendedor  |    6500 |
+---------+-----------+---------+
1 row in set (0.001 sec)

MariaDB [meu_banco_de_dados]> SELECT p_nome, profissao, salario
    -> FROM funcionarios
    -> WHERE profissao = 'Vendedor'
    -> OR salario > 3000;
+---------+-------------------+---------+
| p_nome  | profissao         | salario |
+---------+-------------------+---------+
| Eveline | Vendedor          |    3400 |
| Osvaldo | Vendedor          |    3400 |
| Maria   | Gerente de vendas |    8500 |
| Mariana | Diretor           |    5000 |
| Marisa  | Gerente           |    9000 |
| Fabiana | Vendedor          |    6500 |
+---------+-------------------+---------+
6 rows in set (0.001 sec)

Utilizando WHERE E ORDER BY juntos

Você já pode perceber que até as consultas mais simples nos permitem analisar os dados com precisão e flexibilidade para encontrar o que procuramos. Aprendemos a usar as palavras chaves AND e OR para definir mais de uma condição ao selecionar dados. E ainda aprendemos a utilizar a declaração WHERE e organizar os dados com a declaração ORDER BY.
Agora vamos combinar o que aprendemos nesse tutorial num exemplo. O SQL é específico quanto à ordem das palavras chaves, então siga essa ordem:

SELECT nome_colunas
FROM nome_tabelas
WHERE condição
ORDER BY nome_colunas;

Veja um exemplo utilizando os conhecimentos que você acabou de adquirir:

MariaDB [meu_banco_de_dados]> SELECT p_nome, profissao, salario
    -> FROM funcionarios
    -> WHERE p_nome LIKE 'Mar' OR salario > 3400
    -> ORDER BY id DESC;
+---------+-------------------+---------+
| p_nome  | profissao         | salario |
+---------+-------------------+---------+
| Fabiana | Vendedor          |    6500 |
| Marisa  | Gerente           |    9000 |
| Mariana | Diretor           |    5000 |
| Maria   | Gerente de vendas |    8500 |
+---------+-------------------+---------+
4 rows in set (0.001 sec)

Note que não selecionamos a coluna id, mas podemos utilizá-la com a declaração ORDER BY.

sexta-feira, 14 de agosto de 2020

Criando seu primeiro banco de dados e tabela com SQL

Photo by Jeremy Manoto on Unsplash

A linguagem SQL oferece mais do que um meio de obter informações de um banco de dados. Com ela podemos definir as estruturas que serão utilizadas para guardar e organizar os dados. A principal estrutura e a TABLE (tabela).
Uma tabela funciona como uma grade, com linhas e colunas. Essas linhas e colunas criam células (como no Excel), onde podemos armazenar os dados. As linhas possuem colunas e, colunas armazenam dados. Os dados mais comuns são do tipo números, datas e strings (cadeia de caracteres). A linguagem SQL nos permite criar uma estrutura de tabela e definir como essa tabela se relaciona com outras no banco de dados. Outro uso comum do SQL é fazer consultas, para extrair dados, das tabelas.
Tabela é a principal estrutura que você deve aprender para entender os dados do banco de dados. Quando começar a trabalhar com um banco de dados novo, a primeira coisa que você deve fazer é olhar as tabelas. Procure por algo que possa chamar sua atenção nos nomes das tabelas e na estrutura das colunas. A coluna contem texto, número ou os dois? Qual é a quantidade de linhas em cada tabela?
Em seguida, veja quantas tabelas existem. O mais simples dos bancos de dados pode ter apenas uma tabela. Um banco de dados que armazena dados de clientes pode ter dezenas de tabelas, até mesmo centenas. Com essa informação você vai saber o quanto de dados você vai precisar analisar.

Criando um banco de dados com SQL

Os programas que vamos utilizar para nesse tutorial é o MariaDB e o MySQL. Esses programas são conhecidos como sistemas de gerenciamento de banco de dados. Com esses softwares podemos definir, criar e consultar bancos de dados. Ao instalar um desses programas, ele vai criar um servidor de banco de dados que já possui um banco de dados chamado mysql. Esse banco de dados contêm objetos que inclui usuários, tabelas e muito mais.
Nesse tutorial de SQL, e nos próximos, vamos usar o MariaDB e o MySQL a partir do terminal (Linux) e Prompt de Comando (Windows). Você pode utilizar tanto o MySQL quanto o MariaDB. A diferença entre os dois é quase só o nome.
Depois de instalar, qualquer um dos dois programas, digite mysql no terminal ou no prompt de comando. Você deve ver uma tela parecida com essa: 

Para ver os bancos de dados use a declaração SHOW DATABASES;. Esse comando vai lista todos os bancos de dados presentes na sua máquina. 

Não vamos mexer com nenhum desses bancos de dados, vamos criar o nosso próprio banco de dados. Para fazer isso precisamos digitar apenas uma linha: CREATE DATABASE meu_banco_de_dados;

Para criar um novo banco de dados utilizamos duas palavras chaves - CREATE e DATABASE - seguido pelo nome do banco de dados. Após o nome do novo banco de dados, terminamos a instrução com ponto e vírgula. O ponto e vírgula é utilizado para encerrar todas as instruções da linguagem SQL.
Agora que criamos um banco de dados vamos olhar os bancos de dados novamente e ver o nosso banco de dados meu_banco_de_dados

Criando uma tabela com SQL

É nas tabelas que os dados são armazenados e o relacionamento definido. Para criar uma tabela precisamos informar o seu nome e o tipo de dados que essa coluna vai guardar. O tipo de dado de uma coluna é muito importante, é esse tipo de dado que defini quais dados podem ser guardados na coluna. Por exemplo, uma coluna do tipo numérico, se você tentar guardar dados do tipo data ou texto vai gerar um erro.
Podemos acessar e analisar os dados das tabelas com declarações SQL. Também podemos visualizar e alterar os dados da tabela facilmente, se suas necessidades mudarem mais tarde.
Agora vamos criar uma tabela no nosso banco de dados meu_banco_de_dados.

Declaração CREATE TABLE do SQL

Vamos criar uma tabela dentro do nosso banco de dados para guardar informações sobre funcionários. As informações que vamos guardar são básicas: nome, salário, profissão, etc. Nesse primeiro momento vamos criar apenas a estrutura pra guardar os dados. É isso que a declaração CREATE TABLE faz, cria uma estrutura, uma tabela.
Antes de criar uma tabela, precisamos definir em qual banco de dados a tabela será criada. Fazemos isso usando a declaração USE. Veja abaixo, um exemplo de como selecionar o banco de dados e criar uma tabela com SQL:

Agora vamos entender o que acabamos de fazer. A declaração USE seleciona o banco de dados. Com a declaração CREATE TABLE funcionarios (...); criamos uma tabela com o nome funcionarios. Dentro dos parênteses, da declaração CREATE TABLE, definimos os nomes das colunas e o tipo de dados que essa coluna vai guardar. A primeira coluna é a de id. Essa coluna vai guardar somente dados do tipo inteiro (1, 2, 3, etc). Na segunda linha, dentro dos parênteses, criamos uma coluna chamada u_nome e definimos que ela vai guardar até 25 caracteres (a, b, c, 1, 23, #, etc). A coluna data_inicio vai guardar dados do tipo data (DD-MM-AAAA). E por fim a coluna salario vai guardar dados do tipo numérico (1, 0.23, 7865, etc).

Declaração INSERT do SQL

Para inserir dados numa tabela usamos a declaração INSERT INTO nome_da_tabela. Nessa declaração também definimos quais colunas vão receber valores. Veja o exemplo abaixo:

Na primeira linha definimos em qual tabela vamos inserir os dados. Na segunda linha definimos quais colunas vão receber os dados. VALUES indica o conjunto de valores que vão ser guardados na tabela. Cada conjunto de valores com o id, p_nome, u_nome, profissao, data_inicio e salario é passado entre parênteses e separados por vírgula. Note que todas essas linhas fazem parte de uma instrução, por isso só existe um ponto e vírgula. Essa instrução pode ser escrita numa linhas apenas.
Para ver os dados gravados use a declaração SELECT * FROM funcionarios;. Vamos aprender a utilizar essa declaração no próximo tutorial.

quinta-feira, 13 de agosto de 2020

Hash MD5 no Python

Imagem de TheDigitalWay por Pixabay

Os hashes criptográficos são muitos utilizados no dia-a-dia. Esse tipo de criptografia esta mais presente na sua vida do que você imagina. Por exemplo, eles são utilizados em assinaturas digitais, detecção de manipulação, códigos de autenticação de mensagens, impressões digitais, somas de verificação (verificação de integridade de mensagem ou arquivo), tabelas de hash, armazenamento de senha e muito mais. Os hashes têm mostrados a sua utilidade no envio de mensagens pela rede e para a segurança no armazenamento de senhas em servidores. Isso porque, a mensagem ou senha não fica salva diretamente no banco de dados, apenas o seu hash. Desse modo, mesmo que o banco de dados seja invadido as senhas estão salvas. Pelo menos em teoria (Nada é cem por cento seguro).
Para trabalhar com hash, python fornece várias funções no módulo hashlib. Nesse tutorial, vamos utilizar algumas dessas funções e explicar seu funcionamento do hash MD5.

MD5 Hash

A função de hash MD5 aceita sequências de bytes e retorna um valor hash de 128 bits. Esse hash é muito utilizado para verificar a integridade dos dados. Você já deve ter baixado algum arquivo, de um site, onde o hash MD5 é disponibilizado. Esse hash md5 é disponibilizado para que você possa ter certeza que o arquivo que você baixou é o mesmo que você queria. Geralmente são sites de torrents que fazem isso.
Essas são as funções que vamos utilizar para criar um hash md5:

  • encode(): Converte a string em bytes para ser aceitável pela função hash.
  • digest(): Retorna os dados codificados em formato de byte.
  • hexdigest(): Retorna os dados codificados em formato hexadecimal.

No exemplo abaixo, vamos passar um valor em bytes e vamos receber uma saída em bytes:

import hashlib 
  
# codificando a string Acervo Lima usando a função de hash md5
hash = hashlib.md5(b'Acervo Lima') 
  
# imprimir o equivalente em bytes. 
print("Equivalente em bytes ao hash: ", hash.digest())

No exemplo, chamamos a função md5() passando um valor em bytes. A função md5() faz a codificação dessa string e, depois, chamamos a função digest(). A função digest() retorna o resultado da função md5() em bytes.
Mas os hashes que vemos por ai não são disponibilizados em bytes, mas sim em hexadecimal. No exemplo abaixo, vamos retornar um hash md5 em hexadecimal.

>>> string = 'Acervo Lima'.encode()
>>> hash = hashlib.md5(string)
>>> print('O equivalente em hexadecimal ao hash: ',
... hash.hexdigest())
O equivalente em hexadecimal ao hash:  409b83920744582bf8b286e4e63e2207

Nesse exemplo, convertemos a string 'Acervo Lima' em bytes usando a função encode(). Depois, chamamos a função md5() para obter o hash md5 em bytes. E, em seguida, chamamos a função hexdigest(). A função hexdigest() converte os bytes em hexadecimal.

Referência:
Módulo hashlib

quarta-feira, 12 de agosto de 2020

concat() e append() do pandas, como usar

Imagem de Steve Buissinne por Pixabay

A biblioteca pandas possui várias facilidades para juntar séries e dataframes com outros tipos de conjuntos de dados. Nesse tutorial vamos aprender algumas dessas facilidades. Os métodos mais utilizados para concatenar uma série ou dataframe é o concat() e o append().

Concatenando Séries e DataFrames com o método concat

A função concat() é utilizada para concatenar (juntar) séries ou dataframes ao longo de um eixo. Com o método concat() podemos definir o eixo em que o método deve operar, isso no caso dos dataframes visto que as séries possuem somente um eixo. Antes de nos aprofundarmos nos parâmetros e peculiaridades desse método, vamos ver um exemplo simples de como o método opera.

>>> import pandas as pd
>>> dados1 = {
... 'A': ['A0', 'A1', 'A2', 'A3'],
... 'B': ['B0', 'B1', 'B2', 'B3'],
... 'C': ['C0', 'C1', 'C2', 'C3'],
... 'D': ['D0', 'D1', 'D2', 'D3']
... }
>>> dados2 = {
... 'A': ['A4', 'A5', 'A6', 'A7'],
... 'B': ['B4', 'B5', 'B6', 'B7'],
... 'C': ['C4', 'C5', 'C6', 'C7'],
... 'D': ['D4', 'D5', 'D6', 'D7']
... }
>>> dados3 = {
... 'A': ['A8', 'A9', 'A10', 'A11'],
... 'B': ['B8', 'B9', 'B10', 'B11'],
... 'C': ['C8', 'C9', 'C10', 'C11'],
... 'D': ['D8', 'D9', 'D10', 'D11']
... }
>>> df1 = pd.DataFrame(dados1, index=[0, 1, 2, 3])
>>> df2 = pd.DataFrame(dados1, index=[4, 5, 6, 7])
>>> df3 = pd.DataFrame(dados1, index=[8, 9, 10, 11])
>>> frames = [df1, df2, df3]
>>> resultado = pd.concat(frames)
>>> resultado
     A   B   C   D
0   A0  B0  C0  D0
1   A1  B1  C1  D1
2   A2  B2  C2  D2
3   A3  B3  C3  D3
4   A0  B0  C0  D0
5   A1  B1  C1  D1
6   A2  B2  C2  D2
7   A3  B3  C3  D3
8   A0  B0  C0  D0
9   A1  B1  C1  D1
10  A2  B2  C2  D2
11  A3  B3  C3  D3

O método concat() recebe uma lista ou dicionário e os junta de acordo com o eixo.
Sem contesto o exemplo acima deve ficar um pouco mais complicado de entender. Vamos voltar a ele. Digamos que você queira associar um rótulo para cada dataframe que foi concatenado. Assim fica mais fácil de saber onde cada dataframe foi posicionado. Podemos fazer isso passando os rótulos para o parâmetro keys.

>>> resultado = pd.concat(frames, keys=['X', 'Y', 'Z'])
>>> resultado
       A   B   C   D
X 0   A0  B0  C0  D0
  1   A1  B1  C1  D1
  2   A2  B2  C2  D2
  3   A3  B3  C3  D3
Y 4   A0  B0  C0  D0
  5   A1  B1  C1  D1
  6   A2  B2  C2  D2
  7   A3  B3  C3  D3
Z 8   A0  B0  C0  D0
  9   A1  B1  C1  D1
  10  A2  B2  C2  D2
  11  A3  B3  C3  D3

Adicionando esses rótulos criamos um índice hierárquico. Com essa vantagem podemos selecionar cada bloco pelo seu rótulo usando o atributo loc.

>>> resultado.loc['X']
    A   B   C   D
0  A0  B0  C0  D0
1  A1  B1  C1  D1
2  A2  B2  C2  D2
3  A3  B3  C3  D3

Com esse exemplo, você já pode ver como esse atributo pode ser útil. Para saber mais sobre o atributo loc, veja nosso tutorial sobre Seleção de subconjuntos de dados.

Definindo o critério de concatenação dos eixos

Os DataFrames pandas possuem dois eixos, o eixo de índice (eixo 0) e o eixo das colunas (eixo 1). Quando juntamos dois ou mais dataframes temos que decidir o que fazer com os outros eixos (além do que estamos concatenando). As opções que temos são as seguintes:

  • join='outer': Fazer a união de todos os eixos. Esse é o valor padrão. Essa opção evita perdas de dados.
  • join='inner': Fazer uma interseção dos eixos.

Vamos ver exemplos de como funciona cada uma das opções.

>>> dados4 = {
...     'B': ['B2', 'B3', 'B6', 'B7'],
...     'D': ['D2', 'D3', 'D6', 'D7'],
...     'F': ['F2', 'F3', 'F6', 'F7']
... }
>>> df4 = pd.DataFrame(dados4, index=[2, 3, 6, 7])
>>> resultado = pd.concat([df1, df4], axis=1, join='outer')
>>> resultado
     A    B    C    D    B    D    F
0   A0   B0   C0   D0  NaN  NaN  NaN
1   A1   B1   C1   D1  NaN  NaN  NaN
2   A2   B2   C2   D2   B2   D2   F2
3   A3   B3   C3   D3   B3   D3   F3
6  NaN  NaN  NaN  NaN   B6   D6   F6
7  NaN  NaN  NaN  NaN   B7   D7   F7

Nesse exemplo, usamos dois dataframes com o número de índices e colunas diferentes. Isso para ficar claro que passando o valor ‘outer’, para o parâmetro join, o método concat() vai tentar organizar os dois dataframes de uma forma que nenhum dado seja perdido. Se você olhar atentamente vai ver que o segundo dataframe (df4) começa no índice dois e na coluna segunda coluna B. Como o primeiro dataframe (df1) possui o mesmo índice não foi preciso criar um novo. Isso não acontece com a coluna B, não da pra encaixar essas colunas. Então novas são criadas. Por isso temos elementos vazios no dataframe resultado. Se o parâmetro join for omitido, o resultado é o mesmo porque o valor padrão desse parâmetro é ‘outer’.
Agora, vamos ver um exemplo passando o valor ‘inner’:

>>> resultado = pd.concat([df1, df4], axis=1, join='inner')
>>> resultado
    A   B   C   D   B   D   F
2  A2  B2  C2  D2  B2  D2  F2
3  A3  B3  C3  D3  B3  D3  F3

Nesse exemplo, podemos ver que perdemos muitos dados. Isso porque, quando passamos o valor ‘inner’ para o parâmetro join, estamos dizendo para o método que queremos apenas os dados dos índices que os dois dataframes tem em comum (no caso, 2 e 3). Você pode verificar que todos os dados dos índices 2 e 3, dos dois dataframes (df1 e df4), foram concatenados e os dados dos outro índices foram perdidos.
Nos dois últimos exemplos, concatenamos os dataframes no eixo 1 (colunas), mas podemos usar o eixo 0 (índice). Nesse caso, no primeiro exemplo o método concat() vai tentar unir as colunas. E no segundo exemplo, apenas as colunas em comum seriam concatenadas (B e D).

>>> resultado = pd.concat([df1, df4], axis=0, join='outer')
>>> resultado
     A   B    C   D    F
0   A0  B0   C0  D0  NaN
1   A1  B1   C1  D1  NaN
2   A2  B2   C2  D2  NaN
3   A3  B3   C3  D3  NaN
2  NaN  B2  NaN  D2   F2
3  NaN  B3  NaN  D3   F3
6  NaN  B6  NaN  D6   F6
7  NaN  B7  NaN  D7   F7
>>> resultado = pd.concat([df1, df4], axis=0, join='inner')
>>> resultado
    B   D
0  B0  D0
1  B1  D1
2  B2  D2
3  B3  D3
2  B2  D2
3  B3  D3
6  B6  D6
7  B7  D7

O nosso dataframe, resultante da concatenação de dois dataframes, pode ter a mesma quantidade de linhas do primeiro dataframe, e o excedente (do segundo dataframe) é perdido.

>>> resultado = pd.concat([df1, df4], axis=1).reindex(df1.index)
>>> resultado
    A   B   C   D    B    D    F
0  A0  B0  C0  D0  NaN  NaN  NaN
1  A1  B1  C1  D1  NaN  NaN  NaN
2  A2  B2  C2  D2   B2   D2   F2
3  A3  B3  C3  D3   B3   D3   F3

Usando o método append do pandas

Se você deseja concatenar dataframes somente no eixo 0 (índice), uma escolha interessante é o método append. Esse método concatena as series e os dataframes ao longo do eixo 0.

>>> resultado = df1.append(df2)
>>> resultado
    A   B   C   D
0  A0  B0  C0  D0
1  A1  B1  C1  D1
2  A2  B2  C2  D2
3  A3  B3  C3  D3
4  A0  B0  C0  D0
5  A1  B1  C1  D1
6  A2  B2  C2  D2
7  A3  B3  C3  D3

Você pode passar uma lista de objetos para serem concatenados.

>>> resultado = df1.append([df2, df3])
>>> resultado
     A   B   C   D
0   A0  B0  C0  D0
1   A1  B1  C1  D1
2   A2  B2  C2  D2
3   A3  B3  C3  D3
4   A0  B0  C0  D0
5   A1  B1  C1  D1
6   A2  B2  C2  D2
7   A3  B3  C3  D3
8   A0  B0  C0  D0
9   A1  B1  C1  D1
10  A2  B2  C2  D2
11  A3  B3  C3  D3

Ignorando índices

Você pode ignorar os índices completamente passando o valor True para o parâmetro ignore_index (Se esses dados não forem importantes). Desse modo, o método vai concatenar os dataframes de acordo com as colunas. Por exemplo, se os dois dataframes têm uma coluna chamada B, essas colunas ficaram uma embaixo da outra.

>>> resultado = pd.concat([df1, df4], ignore_index=True)
>>> resultado
     A   B    C   D    F
0   A0  B0   C0  D0  NaN
1   A1  B1   C1  D1  NaN
2   A2  B2   C2  D2  NaN
3   A3  B3   C3  D3  NaN
4  NaN  B2  NaN  D2   F2
5  NaN  B3  NaN  D3   F3
6  NaN  B6  NaN  D6   F6
7  NaN  B7  NaN  D7   F7

O mesmo parâmetro funciona no método append().

Concatenando séries com dataframes

Você pode concatenar séries com dataframes. O método concat() pode trabalhar com os dois tipos. Nesse exemplo, vamos criar uma série e concatená-la com um dataframe. Essa série será adicionada como uma coluna no final do dataframe.

>>> s1 = pd.Series(['X0', 'X1', 'X2', 'X3'], name='X')
>>> resultado = pd.concat([df1, s1], axis=1)
>>> resultado
    A   B   C   D   X
0  A0  B0  C0  D0  X0
1  A1  B1  C1  D1  X1
2  A2  B2  C2  D2  X2
3  A3  B3  C3  D3  X3

Se a série não tiver um nome, será atribuído uma sequencia de números.

>>> s2 = pd.Series(['_0', '_1', '_2', '_3'])
>>> resultado = pd.concat([df1, s2, s2, s2], axis=1)
>>> resultado
    A   B   C   D   0   1   2
0  A0  B0  C0  D0  _0  _0  _0
1  A1  B1  C1  D1  _1  _1  _1
2  A2  B2  C2  D2  _2  _2  _2
3  A3  B3  C3  D3  _3  _3  _3

Podemos usar o parâmetro ignore_index e definir os rótulos das colunas com uma sequencia numérica desde a primeira coluna.

>>> resultado = pd.concat([df1, s2, s2, s2], axis=1, ignore_index=True)
>>> resultado
    0   1   2   3   4   5   6
0  A0  B0  C0  D0  _0  _0  _0
1  A1  B1  C1  D1  _1  _1  _1
2  A2  B2  C2  D2  _2  _2  _2
3  A3  B3  C3  D3  _3  _3  _3

Concatenando com um grupo de keys

O padrão é o novo dataframe herdar os nomes das colunas dos dataframes pais. Podemos mudar isso com o parâmetro keys. O uso mais comum do parâmetro keys é exatamente esse: substituir o nome das colunas.

>>> pd.concat([s3, s4, s5], axis=1)
   um  dois  tres
0   0     0     1
1   1     1     4
2   2     1     1
3   3     3     4
>>> pd.concat([s3, s4, s5], axis=1, keys=['X', 'Y', 'Z'])
   X  Y  Z
0  0  0  1
1  1  1  4
2  2  1  1
3  3  3  4

Podemos fazer a mesma coisa com um dicionário.

>>> dicio = {'X':s3, 'Y':s4, 'Z':s5}
>>> resultado = pd.concat(dicio, axis=1)
>>> resultado
   X  Y  Z
0  0  0  1
1  1  1  4
2  2  1  1
3  3  3  4

Referência:
Função concat()
Função append()

Como usar a função groupby() do pandas

Photo by Duy Pham on Unsplash

Python é uma ótima linguagem para fazer análise de dados, principalmente por causa do fantástico ecossistema de pacotes python desenvolvidos para a análise de dados. pandas é um desses pacotes. Com ele podemos importar dados de um dataset e realizar algumas analises facilmente, como agrupar dados. O método groupby é muito utilizado para esse proposito.
O que o método groupby faz é separar os dados por grupos. Com os dados agrupados é comum aplicar uma função e combinar o resultado. Por exemplo, a velocidade de um falcão-peregrino vária de 370km/h à 390km/h e um papagaio de 24km/h à 26km/h. Com esses dados podemos usar o método groupby (para agrupar os dados) e o método mean (média) para saber qual é a velocidade média de cada ave.
Com os dados de cada ave, o método groupby vai agrupar os dados por categoria, no caso a categoria é o animal. Com esses dados agrupados podemos chamar o método mean(), que fornece a média dos valores. Desse modo temos um dataframe com a velocidade média de cada animal.

>>> import pandas as pd
>>> dados = {
... 'Animal': ['Falcao', 'Papagaio', 'Falcao', 'Papagaio'],
... 'Velocidade_maxima':[390, 24, 370, 26]
... }
>>> df = pd.DataFrame(dados)
>>> df
     Animal  Velocidade_maxima
0    Falcao                390
1  Papagaio                 24
2    Falcao                370
3  Papagaio                 26

>>> df.groupby(['Animal']).mean()
          Velocidade_maxima
Animal
Falcao                  380
Papagaio                 25

Quer aprender mais sobre a biblioteca pandas? Comece com nossos tutoriais pandas.

Referência:
Função groupby()
Função DataFrame()