DEV Community

Cover image for Filtros e a criação de colunas no pandas podem ser mais simples.
Bruno
Bruno

Posted on

2 1

Filtros e a criação de colunas no pandas podem ser mais simples.

Todo mundo que trabalha usando o pandas às vezes se depara com uma linha de código com uma centena de caracteres, que na prática só faz uma série de filtros aninhados com condições de “e” e “ou” quase que infinitas.

df[
    (df['Classificação'] != "Normal") 
    & 
    (df['Altura'] < 1.70)
    & 
    (df['Peso'] > 60)
]
Enter fullscreen mode Exit fullscreen mode

O Grande problema disso é que é muito fácil se perder nesses filtros com indexação booleana e é bem trabalhoso para dar manutenção em caso de bugs ou se houver a necessidade de complementar os filtros.

Para criar colunas em função de outras, geralmente usamos uma série de caracteres repetidos e isso nos soa um alerta de que talvez haja ou deveria haver uma forma mais simples de fazer isso.

df2['IMC'] = df2['Peso'] / df2['Altura'] ** 2 
Enter fullscreen mode Exit fullscreen mode

Então eu vou demonstrar a melhor forma que eu encontrei para fazer essas operações ficarem mais legíveis:

import pandas as pd

# Criando dois dataframes para os exemplos:
df = pd.DataFrame({"Altura":[1.75, 1.64, 1.50, 1.45, 1.90],
                    "Peso": [90,85,70,60,75]})

df2 = pd.DataFrame({"Altura":[1.75, 1.64, 1.50, 1.45, 1.90],
                     "Peso": [90,85,70,60,75]})

# Fazendo um cálculo com base nos valores de duas colunas:
df2['IMC'] = df2['Peso'] / df2['Altura'] ** 2
Enter fullscreen mode Exit fullscreen mode
Altura Peso IMC
0 1.75 90 29.3878
1 1.64 85 31.6032
2 1.5 70 31.1111
3 1.45 60 28.5375
4 1.9 75 20.7756

O Jeito mais legível é com o método eval. Basta montar a expressão como uma string simples:

df.eval("IMC = Peso / Altura ** 2", inplace=True)
```
{% endraw %}

|    |   Altura |   Peso |     IMC |
|---:|---------:|-------:|--------:|
|  0 |     1.75 |     90 | 29.3878 |
|  1 |     1.64 |     85 | 31.6032 |
|  2 |     1.5  |     70 | 31.1111 |
|  3 |     1.45 |     60 | 28.5375 |
|  4 |     1.9  |     75 | 20.7756 |

Também podemos criar colunas usando funções, selecionando a coluna e com o metodo apply passar o nome da função como parâmetro. Geralmente é a minha última alternativa e  compensa em casos envolvendo muitos "ifs".
{% raw %}


```python
def classificacao_imc(imc):
    if imc < 18.5:
        return "Magro"
    elif imc >= 18.5 and imc <= 24.9:
        return "Normal"
    elif imc > 24.9 and imc < 29.9:
        return "Sobrepeso"
    elif imc >= 30.0 and imc  < 39.9:
        return "Obesidade"
    elif imc >= 40:
        return "Obesidade Grave"

# e então:
df["Classificação"] = df['IMC'].apply(classificacao_imc)

print(df)
```
{% endraw %}

|    |   Altura |   Peso |     IMC | Classificação   |
|---:|---------:|-------:|--------:|:----------------|
|  0 |     1.75 |     90 | 29.3878 | Sobrepeso       |
|  1 |     1.64 |     85 | 31.6032 | Obesidade       |
|  2 |     1.5  |     70 | 31.1111 | Obesidade       |
|  3 |     1.45 |     60 | 28.5375 | Sobrepeso       |
|  4 |     1.9  |     75 | 20.7756 | Normal          |
{% raw %}

````python
df2["Classificação"] = df2['IMC'].apply(classificacao_imc)

df.eval("Peso_ideal = 24.9 * Altura ** 2", inplace=True)
df2.eval("Peso_ideal = 24.9 * Altura ** 2", inplace=True)
print(df)
```
{% endraw %}

|    |   Altura |   Peso |     IMC | Classificação   |   Peso_ideal |
|---:|---------:|-------:|--------:|:----------------|-------------:|
|  0 |     1.75 |     90 | 29.3878 | Sobrepeso       |      76.2562 |
|  1 |     1.64 |     85 | 31.6032 | Obesidade       |      66.971  |
|  2 |     1.5  |     70 | 31.1111 | Obesidade       |      56.025  |
|  3 |     1.45 |     60 | 28.5375 | Sobrepeso       |      52.3522 |
|  4 |     1.9  |     75 | 20.7756 | Normal          |      89.889  |

Filtro do jeito clássico (indexação booleana):
{% raw %}


````python
df[df['Classificação'] != 'Normal']
```
{% endraw %}

|    |   Altura |   Peso |     IMC | Classificação   |   Peso_ideal |
|---:|---------:|-------:|--------:|:----------------|-------------:|
|  0 |     1.75 |     90 | 29.3878 | Sobrepeso       |      76.2562 |
|  1 |     1.64 |     85 | 31.6032 | Obesidade       |      66.971  |
|  2 |     1.5  |     70 | 31.1111 | Obesidade       |      56.025  |
|  3 |     1.45 |     60 | 28.5375 | Sobrepeso       |      52.3522 |

#### Filtro do jeito mais legível, com o método query.
Você  precisa passar uma string com os nomes de colunas e comparar com strings (coloque '  ao redor), números ou variáveis. Para comparar com variáveis, basta usar @nome_da_variável.
{% raw %}


```python
df2.query("Classificação != 'Normal'")
```


|    |   Altura |   Peso |     IMC | Classificação   |   Peso_ideal |
|---:|---------:|-------:|--------:|:----------------|-------------:|
|  0 |     1.75 |     90 | 29.3878 | Sobrepeso       |      76.2562 |
|  1 |     1.64 |     85 | 31.6032 | Obesidade       |      66.971  |
|  2 |     1.5  |     70 | 31.1111 | Obesidade       |      56.025  |
|  3 |     1.45 |     60 | 28.5375 | Sobrepeso       |      52.3522 |



```python
variavel = 'Obesidade'
df2.query("Classificação == @variavel")
```



|    |   Altura |   Peso |     IMC | Classificação   |   Peso_ideal |
|---:|---------:|-------:|--------:|:----------------|-------------:|
|  1 |     1.64 |     85 | 31.6032 | Obesidade       |       66.971 |
|  2 |     1.5  |     70 | 31.1111 | Obesidade       |       56.025 |

Filtro aninhado e com indexação booleana:


```python
df[
    (df['Classificação'] != "Normal") 
    & 
    (df['Altura'] < 1.70)
    & 
    (df['Peso'] > 60)
]
```


|    |   Altura |   Peso |     IMC | Classificação   |   Peso_ideal |
|---:|---------:|-------:|--------:|:----------------|-------------:|
|  1 |     1.64 |     85 | 31.6032 | Obesidade       |       66.971 |
|  2 |     1.5  |     70 | 31.1111 | Obesidade       |       56.025 |

Com o método query:



```python
df.query("Classificação != 'Normal'and Altura < 1.70 and Peso > 60")
```


|    |   Altura |   Peso |     IMC | Classificação   |   Peso_ideal |
|---:|---------:|-------:|--------:|:----------------|-------------:|
|  1 |     1.64 |     85 | 31.6032 | Obesidade       |       66.971 |
|  2 |     1.5  |     70 | 31.1111 | Obesidade       |       56.025 |

Você também pode fazer:


```python
query_string = (
    "Classificação != 'Normal'"
    "and Altura < 1.70"
    "and Peso > 60"
)

df.query(query_string)
```


|    |   Altura |   Peso |     IMC | Classificação   |   Peso_ideal |
|---:|---------:|-------:|--------:|:----------------|-------------:|
|  1 |     1.64 |     85 | 31.6032 | Obesidade       |       66.971 |
|  2 |     1.5  |     70 | 31.1111 | Obesidade       |       56.025 |

Por fim:



```python
query_string = (
    "Classificação != 'Normal'"
    "and Altura < 1.70"
    "and Peso > 60"
)
df.query(query_string)
```


É mais legível e organizado do que:



```python
df[
    (df['Classificação'] != "Normal") 
    & 
    (df['Altura'] < 1.70)
    & 
    (df['Peso'] > 60)
]
```




Não?


Enter fullscreen mode Exit fullscreen mode

AWS Q Developer image

Your AI Code Assistant

Automate your code reviews. Catch bugs before your coworkers. Fix security issues in your code. Built to handle large projects, Amazon Q Developer works alongside you from idea to production code.

Get started free in your IDE

Top comments (0)

👋 Kindness is contagious

Engage with a wealth of insights in this thoughtful article, valued within the supportive DEV Community. Coders of every background are welcome to join in and add to our collective wisdom.

A sincere "thank you" often brightens someone’s day. Share your gratitude in the comments below!

On DEV, the act of sharing knowledge eases our journey and fortifies our community ties. Found value in this? A quick thank you to the author can make a significant impact.

Okay