SQL vs Pandas - Agrupamento e frequências

SQL vs Pandas - Agrupamento e frequências

Neste artigo vamos ver como calcular a frequência absoluta e relativa de um conjunto de registros comparando como isso pode serfeito no SQL e no Pandas. Vamos ver uma tabela de vendas com dados de um determinado periodo e faremos o seu agrupamento por período para poder fazer estes cálculos.

Primeiro vamos criar as tabelas e popular os dados. Vamos começar pelo SQL

 

MySQL

CREATE TABLE vendas (

id int NOT NULL AUTO_INCREMENT,

mes int,

produto int,

quantidade int,

PRIMARY KEY (id)

);

 

SQL SERVER

CREATE TABLE vendas (

id int IDENTITY(1,1) PRIMARY KEY,

mes int,

produto int,

quantidade int

);

 

Depois de criar as tabelas, vamos inserir os dados que serão utilizados

 

INSERT INTO vendas (mes, produto, quantidade) VALUES (1,1,10);

INSERT INTO vendas (mes, produto, quantidade) VALUES (1,2,20);

INSERT INTO vendas (mes, produto, quantidade) VALUES (1,2,30);

INSERT INTO vendas (mes, produto, quantidade) VALUES (2,1,12);

INSERT INTO vendas (mes, produto, quantidade) VALUES (2,2,26);

INSERT INTO vendas (mes, produto, quantidade) VALUES (2,2,34);

INSERT INTO vendas (mes, produto, quantidade) VALUES (3,1,13);

INSERT INTO vendas (mes, produto, quantidade) VALUES (3,2,21);

INSERT INTO vendas (mes, produto, quantidade) VALUES (3,2,36);

INSERT INTO vendas (mes, produto, quantidade) VALUES (4,1,14);

INSERT INTO vendas (mes, produto, quantidade) VALUES (4,2,27);

INSERT INTO vendas (mes, produto, quantidade) VALUES (4,2,32);

INSERT INTO vendas (mes, produto, quantidade) VALUES (5,1,12);

INSERT INTO vendas (mes, produto, quantidade) VALUES (5,2,23);

INSERT INTO vendas (mes, produto, quantidade) VALUES (5,2,35);

INSERT INTO vendas (mes, produto, quantidade) VALUES (6,1,14);

INSERT INTO vendas (mes, produto, quantidade) VALUES (6,2,26);

INSERT INTO vendas (mes, produto, quantidade) VALUES (6,2,38);

INSERT INTO vendas (mes, produto, quantidade) VALUES (7,1,12);

INSERT INTO vendas (mes, produto, quantidade) VALUES (7,2,27);

INSERT INTO vendas (mes, produto, quantidade) VALUES (7,2,35);

INSERT INTO vendas (mes, produto, quantidade) VALUES (8,1,14);

INSERT INTO vendas (mes, produto, quantidade) VALUES (8,2,28);

INSERT INTO vendas (mes, produto, quantidade) VALUES (8,2,32);

INSERT INTO vendas (mes, produto, quantidade) VALUES (9,1,11);

INSERT INTO vendas (mes, produto, quantidade) VALUES (9,2,23);

INSERT INTO vendas (mes, produto, quantidade) VALUES (9,2,35);

INSERT INTO vendas (mes, produto, quantidade) VALUES (10,1,11);

INSERT INTO vendas (mes, produto, quantidade) VALUES (10,2,21);

INSERT INTO vendas (mes, produto, quantidade) VALUES (10,2,31);

INSERT INTO vendas (mes, produto, quantidade) VALUES (11,1,9);

INSERT INTO vendas (mes, produto, quantidade) VALUES (11,2,17);

INSERT INTO vendas (mes, produto, quantidade) VALUES (11,2,25);

INSERT INTO vendas (mes, produto, quantidade) VALUES (12,1,8);

INSERT INTO vendas (mes, produto, quantidade) VALUES (12,2,16);

INSERT INTO vendas (mes, produto, quantidade) VALUES (12,2,27);

 

Faremos a mesma operação no Pandas

 

import numpy as np

import pandas as pd

dados = np.array([[1,1,10], [1,2,20], [1,2,30], [2,1,12], [2,2,26], [2,2,34], [3,1,13], [3,2,21], [3,2,36], [4,1,14], [4,2,27], [4,2,32], [5,1,12], [5,2,23], [5,2,35], [6,1,14], [6,2,26], [6,2,38], [7,1,12], [7,2,27], [7,2,35], [8,1,14], [8,2,28], [8,2,32], [9,1,11], [9,2,23], [9,2,35], [10,1,11], [10,2,21], [10,2,31], [11,1,9], [11,2,17], [11,2,25], [12,1,8], [12,2,16], [12,2,27]])

colunas = ["mes", "produto", "quantidade"]

dataframe = pd.DataFrame(data=dados, columns=colunas)

dataframe.sort_values(by=["mes"], ascending=True)

print(dataframe)

 

Nossa primeira tarefa vai ser agrupar as quantidades por mês. No SQL isso é posível agrupando os dados pela coluna mes e utilizando uma função de agrupamento para o campo quantidade que vai fazer a soma das quantidades do período. A soma do período foi obtida utilizando a função SUM().

 

SELECT mes, sum(quantidade) as total FROM vendas GROUP BY mes ORDER BY mes

 

No Pandas faremos exatamente a mesma coisa, um agrupamento por mês e depois a soma da coluna quantidade. Faremos uma cópia do dataframe original para fazer o agrupamento.

 

dataframe2 = dataframe.groupby(["mes"],as_index=False)["quantidade"].sum()

dataframe2.columns = ["mes", "total"]

print(dataframe2)

 

A seguir faremos o cálculo da frequência relativa em porcentagem, vamos calcular quando vale cada período em percentual em relação ao todo. No SQL isso pode ser obtido dividindo a soma do periodo pela soma de todos os periodos, a soma de todos os periodos pode ser obtida através de um subselect

 

MySQL

SELECT mes, sum(quantidade) as total, (SUM(quantidade) / (SELECT SUM(quantidade) FROM vendas))*100 as percentual FROM vendas GROUP BY mes ORDER BY mes

SQL Server

SELECT mes, sum(quantidade) as total, (SELECT SUM(quantidade) FROM vendas) as x,

(CAST(SUM(quantidade) as float) / CAST((SELECT SUM(quantidade) FROM vendas) as float))*100 as percentual FROM vendas GROUP BY mes ORDER BY mes

 

Perceba que no caso do SQL Server foi feito um passo a mais em relação a consulta feita no MySQL. Como estamos fazendo a divisão de inteiros, tivemos que fazer a conversão de cada campo usado na divisão para float, para isso utilizamos a função CAST.

 

No Pandas a operação e um pouco mais simples. Podemos criar uma coluna nova no dataframe onde fizemos o agrupamento e dividir o total calculado pela soma de todas as quantidades, para isso podemos usar o método sum() no campo da quantidade

 

dataframe2["percentual"] = (dataframe2["total"] / dataframe2["total"].sum())*100

print(dataframe2)

 

Para encerrar, vamos fazer a soma acumulada em cada período, cada mes vai ser a soma dele mesmo com os valores dos meses anteriores. No SQL isso pode ser obtido mais uma vez utilizando um subselect onde somamos todas as quantidades iguais ou menores que o mes atual.

 

MySQL

SELECT V.mes, sum(V.quantidade) as total, (SUM(V.quantidade) / (SELECT SUM(quantidade) FROM vendas))*100 as percentual, (SELECT SUM(quantidade) FROM vendas WHERE mes <= V.mes) as acumulado FROM vendas as V GROUP BY V.mes ORDER BY V.mes

SQL SERVER

SELECT V.mes, sum(V.quantidade) as total, 

(CAST(SUM(V.quantidade) as float) / CAST((SELECT SUM(quantidade) FROM vendas) as float))*100 as percentual,(SELECT SUM(quantidade) FROM vendas WHERE mes <= V.mes) as acumulado FROM vendas as V GROUP BY V.mes ORDER BY V.mes

 

No Pandas essa operação pode ser feita utilizado o método cumsum() no campo da quantidade. Para isso basta criar uma nova coluna no dataframe usado para o agrupamento e aplicar o método cumsum() na coluna total.

 

dataframe2["acumulado"] = dataframe2["total"].cumsum()

 

Encerramento

 

Neste artigo você viu como calcular frequências absolutas e relativas utilizando o SQL e o Pandas

Se você se interessa por comparações de como resolver o mesmo problema utilizando SQL e o Pandas pode conferir meus artigos anteriores

 

SQL vs Pandas - Operações Básicas

 

SQL vs Pandas - Operações Básicas parte 2

 

SQL vs Pandas - Manipulando strings

 

 

Outros conteudos que podem ser de seu interesse

SQL vs Mongo - expressões regulares
22/12/2019SQL

SQL vs Mongo - expressões regulares

Veja como utilizar expressões regulares no SQL e no Mongo

Saiba mais...
Localizando tabela por data de criação com SQL Server ou MySQL
08/08/2016SQL

Localizando tabela por data de criação com SQL Server ou MySQL

Uma dica rápida para quem trabalha com SQL Server ou MySQL e deseja localizar tabelas por data de criação

Saiba mais...

Conteúdo sobre banco de dados sem complicação!