No primeiro post sobre esse assunto, falei sobre como implementar no Pandas o SELECT e também as clausula WHERE. Para acessar a primeira parte é só clicar aqui.
Agora vou mostrar como tratar funções de agrupamento, junções e uniões.
Group By
O GROUP BY
é utilizado para separar os registros selecionados em grupos específicos. Com os agrupamentos criados, podemos aplicar as funções de agregação, que podem ser contar os registros do grupo, somar valores, valores máximos e mínimos e etc.
Vamos a um exemplo
No código abaixo, contamos os registros agrupados pela coluna sex
.
SELECT sex, count(*) FROM tips GROUP BY sex; /* Female 87 Male 157 */
O equivalente no Pandas pode ser:
In [18]: tips.groupby('sex').size() Out[18]: sex Female 87 Male 157 dtype: int64
Perceba que no pandas usamos size()
e não count()
. Isso acontece porque count()
é aplicado a cada coluna, retornando o número de registros não nulos de cada uma.
Também é possível a busca de várias agregações em uma única instrução. Nesse caso, devemos utilizar a função agg() e passar um dicionário com as colunas e a função desejada. Bem de boa:
SELECT day, AVG(tip), COUNT(*) FROM tips GROUP BY day; /* Fri 2.734737 19 Sat 2.993103 87 Sun 3.255132 76 Thur 2.771452 62 */
In [21]: tips.groupby('day').agg({'tip': np.mean, 'day': np.size}) Out[21]: tip day day Fri 2.734737 19 Sat 2.993103 87 Sun 3.255132 76 Thur 2.771452 62
Inner Join
Utilizadíssimo nos selects, o inner join
é um tipo de junção que busca apenas os dados que existem nas duas tabelas juntadas. Vamos considerar os seguintes DataFrames como exemplo:
In [23]: df1 = pd.DataFrame({'key': ['A', 'B', 'C', 'D'], ....: 'value': np.random.randn(4)}) ....: In [24]: df2 = pd.DataFrame({'key': ['B', 'D', 'D', 'E'], ....: 'value': np.random.randn(4)}) ....:
Assumimos que temos as mesmas tabelas na base com a mesma estrutura
SELECT * FROM df1 INNER JOIN df2 ON df1.key = df2.key;
# merge performs an INNER JOIN by default In [25]: pd.merge(df1, df2, on='key') Out[25]: key value_x value_y 0 B -0.282863 1.212112 1 D -1.135632 -0.173215 2 D -1.135632 0.119209
O método merge()
permite também que o join seja feito por colunas com nomes diferentes:
[in] df1 = pd.DataFrame({'fruta': ['maçã', 'laranja', 'pera', 'pêssego'], 'value': [1, 2, 3, 5]}) [in] df2 = pd.DataFrame({'alimento': ['maçã', 'pão', 'pera', 'pêssego'], 'value': [5, 6, 7, 8]})
[in] df1.merge(df2, left_on='fruta', right_on='alimento', suffixes=('_fruta', '_alimento')) [out] fruta value_fruta alimento value_alimento 0 maçã 1 maçã 5 1 pera 3 pera 7 2 pêssego 5 pêssego 8
Left (Outer) Join
O left join
traz todos os registros da primeira tabela declarada (da esquerda) e se houverem dados tabela relacionada também serão projetados. No exemplo, utilizo o mesmo data frame do inner join
. No pandas, o tipo de junção é passada no parâmetro how
do merge()
.
-- mostra todos os registros de df1 SELECT * FROM df1 LEFT OUTER JOIN df2 ON df1.key = df2.key;
# mostra todos os registros de df1 In [28]: pd.merge(df1, df2, on='key', how='left') Out[28]: key value_x value_y 0 A 0.469112 NaN 1 B -0.282863 1.212112 2 C -1.509059 NaN 3 D -1.135632 -0.173215 4 D -1.135632 0.119209
Union
No pandas temos o mesmo resultado usando a função concat()
.
In [31]: df1 = pd.DataFrame({'city': ['Chicago', 'San Francisco', 'New York City'], ....: 'rank': range(1, 4)}) ....: In [32]: df2 = pd.DataFrame({'city': ['Chicago', 'Boston', 'Los Angeles'], ....: 'rank': [1, 4, 5]})
SELECT city, rank FROM df1 UNION ALL SELECT city, rank FROM df2; /* city rank Chicago 1 San Francisco 2 New York City 3 Chicago 1 Boston 4 Los Angeles 5 */
In [33]: pd.concat([df1, df2]) Out[33]: city rank 0 Chicago 1 1 San Francisco 2 2 New York City 3 0 Chicago 1 1 Boston 4 2 Los Angeles 5
Em SQL, UNION é similar do UNION ALL, porém o UNION remove os registros duplicados.
SELECT city, rank FROM df1 UNION SELECT city, rank FROM df2; -- notice that there is only one Chicago record this time /* city rank Chicago 1 San Francisco 2 New York City 3 Boston 4 Los Angeles 5 */
No Pandas, o método drop_duplicates()
pode ser usado em conjunto com o concat()
para repetir esse comportado.
In [34]: pd.concat([df1, df2]).drop_duplicates() Out[34]: city rank 0 Chicago 1 1 San Francisco 2 2 New York City 3 1 Boston 4 2 Los Angeles 5
Por hoje era isso…
Trouxe apenas um resumo do que me ajudou bastante a pensar mais como pandas e menos sql. Espero que possa ajudar mais alguém. Vou deixar o link da documentação do pandas, especificamente dessa parte, com vários outros exemplos.
Um abraço e até a próxima 😊