# Aula 7 - Análise e visualização de dados em Python - Biblioteca pandas (parte 3)

Nas últimas aulas, foram abordadas vários recursos do pandas que você pode utilizar em suas práticas com dados, abordando também conceitos essenciais para você aproveitar essa biblioteca do Python da melhor maneira. Nessa aula, continuaremos nessa mesma pegada.

Nessa aula, veremos:

- Outros métodos de fatiamento: `loc` e `iloc`;
- Seleções por critérios

## Outros métodos de fatiamento: `loc` e `iloc`

Anteriormente, vimos já alguns métodos do processo chamado de *fatiamento* ou *slicing*, no qual é possível criar novos frames separando linhas e colunas com as quais se quer trabalhar. No pandas, existem uma série de recursos que exploram esse processo, tornando a experiência com a biblioteca mais proveitosa à medida em que vai se dominando as diferentes maneiras de seleção de linhas e colunas. Nessa aula, serão apresentados os métodos `loc`e `iloc`.

### Método `loc` - Localização por rótulos

*Grosso modo*, o método de seleção `loc` seleciona linhas e colunas de acordo com o seu rótulo (*label*), isto é, seu "nome" na tabela, aquilo que aparece visualmente quando temos um *output* de comando. Você pode usar essa seleção de acordo com algumas fórmulas:

- `df.loc[linha]` : Seleciona uma ou mais linhas pelo seu rótulo;
- `df.loc[: , coluna]`: Seleciona uma ou mais colunas pelo seu rótulo;
- `df.loc[linha, coluna]`: Seleciona linhas e colunas pelo seu rótulo.

Vejamos isso em termos práticos, usando o *dataframe* `df`, já nosso conhecido:

```python
df.loc['NL'] #Seleciona as linhas contendo a ID de espécie 'NL'

df.loc['NL', ['sex', 'hindfoot_length']] #Seleciona as linhas nas colunas 'sex' e 'hindfoot_length' contendo a ID de espécie 'NL'

df.loc[:['year','species_id']] #Seleciona as colunas 'year' e 'species_id'

df.loc[['NL', 'DM', 'DO'], ['sex', 'hindfoot_length']] #Seleciona as linhas nas colunas 'sex' e 'hindfoot_length' contendo a IDs de espécie 'NL', 'DM' e 'DO'
```

Acima, portanto, fomos selecionando diversas linhas e colunas observando sempre seus rótulos na tabela. Quando da seleção apenas de colunas, repare o uso do `:` isolado; este indica que serão filtradas todas as linhas do *dataframe*.  A separação de linhas e colunas no comando, repare também, é feita pelo separador `,`. Um outro detalhe importante de se destacar: ao usar os métodos de seleção, atente a utilizar sempre linhas e colunas não-nulas (apontados comumente como `NaN`; veremos o que são dados nulos -  e o que fazer com eles - com mais detalhes em outra aula).

> **Que tal fazer você mesmo?**
>
> Com o primeiro notebook da serie e os dados e a biblioteca pandas importadas nele, experimente fazer uma seleção com espécies e colunas diferentes, sempre usando o `df.loc`. *Pratique bastante, e encorajo-lhe a buscar outras referências e exemplos na literatura ou na Internet para entender melhor. Algumas sugestões de lugares para buscar mais ajuda estarão em "Para ler mais"*

### Método `iloc` - Localização por números inteiros

O método `iloc` segue o mesmo princípio do `loc`, mas com uma diferença essencial: enquanto o `loc` faz uma seleção por rótulos, o `iloc` busca linhas e colunas em relação às suas localizações inteiras (em números). Cada linha e coluna em um *dataframe* possui uma localização inteira que a define, sendo isso uma espécie de acréscimo ao rótulo que é exibido no *output* de cada comando. Essa localização é o número da linha/coluna no qual o nosso alvo estará localizado, sempre começando da parte superior esquerda.

Para usar esse método, podemos nos basear nas seguintes fórmulas:

- `df.iloc[0]`: Seleciona a primeira linha por sua localização inteira;
- `df.iloc[linha]`: Seleciona uma linha por sua localização inteira;
- `df.iloc[:, coluna]`: Seleciona uma coluna por sua localização inteira;

Vejamos isso em termos práticos, usando outra vez o *dataframe* `df`:

```python
df.iloc[0] #Seleciona a primeira linha de 'df'

df.iloc[4] #Seleciona a quinta linha de 'df' (lembre-se: a contagem de linhas no Python começa por 0)

df.iloc[:, 2] #Seleciona a terceira coluna de 'df'

df.iloc[[1, 2], [0, 2, 1]] #Seleciona a segunda e terceira linha, e a primeira, terceira, e segunda coluna de 'df', nesta ordem
```

> **Que tal fazer você mesmo?**
>
> Com os dados de `df`em mãos, aproveite para testar o método `iloc`, localizando diferentes linhas e colunas na tabela. Se você não se lembra a quantidade de linhas e colunas que há no *dataframe*, é simples descobrir: use o comando `df.shape()`. É esperado que o *output* venha na fórmula `(linhas, colunas)`. *Pratique bastante, e encorajo-lhe a buscar outras referências e exemplos na literatura ou na Internet para entender melhor. Algumas sugestões de lugares para buscar mais ajuda estarão em "Para ler mais"*

## Seleções por critérios

No pandas, além de fazermos seleções por posição ou rótulo, também podemos selecionar informações de nossos *dataframes* por uma série de critérios ou condições expressos nas linhas de comando.

### Entendi foi nada: o que seriam esses 'critérios' ou 'condições'?

Como temos conhecimento de como estão dispostos os dados no *dataframe* que estamos utilizando aqui, podemos fazer *subsets* (um *dataframe* do *dataframe*) baseados em normas ou critérios que podemos estabelecer. Se você quiser, por exemplo, separar todas as linhas de amostras que foram coletadas no ano de 2001, apenas é preciso usar um operador lógico do Python para chegar a esse fim, o `==`. Veja um exemplo:

```python
df_2001 = df[df.year == 2001] #Separa as linhas cujo ano, 'year', é igual a 2001
```

Nesse caso, estamos criando um novo *dataframe*, `df_2001`, usando o nosso *frame* principal, `df`, com a condição/critério de que sejam selecionados apenas as linhas que, na coluna `year`, possuam  o valor de ano `2001`. Assim, se chamarmos `df_2001`, aparecerá o *dataframe* criado com a condição que fora estabelecida. 

Não apenas para selecionar valores que coincidam com o critério, podemos usar outros operadores lógicos do Python para criar novos *dataframes*. Tais operadores são, segundo a sintaxe:

- `==`: igual a;
- `!=`: não igual a;
- `>` ou `<`: maior ou menor que;
- `>=`: maior ou igual que;
- `<=`: menor ou igual que.

Se, por algum acaso, queiramos definir mais de um conjunto de critérios, podemos utilizar o operador `&` para conectá-los:

````python
df_conj = df[(df.year >= 1990) & (df.year <= 1995)] #Separa as linhas cujas amostragens possuam valor 'year' maior ou igual a 1990, e menor ou igual a 1995
````

> **Que tal fazer você mesmo?**
>
> Da mesma forma que usamos o `df` para explorar as possibilidades de usar os métodos `loc` e `iloc`, podemos aqui utilizar esse *dataframe* para fitrá-lo de acordo com condições que nós mesmos podemos estabelecer. Assim sendo, você pode explorar os operadores lógicos do Python para escrever algumas linhas de código.

------

Nessa aula vimos mais alguns recursos do pandas para fazer seleções de linhas e colunas, além da criação de *subsets*. Esses são aspectos essenciais a se levar em conta ao trabalhar com dados, uma vez que eles proporcionam uma variedade de possibilidades de se manipular tabelas sem a necessidade de carregar o mesmo *dataset* toda vez; isso facilita, e muito, o trabalho a ser feito. Nas próximas aulas continuaremos a discutir sobre como manipular dados com o pandas; mas antes, será interessante apresentar para vocês algumas características dessa biblioteca no que se refere à visualização de dados. Haverá, portanto, uma apresentação de códigos e conceitos para plotar dados usando pandas. Com isso, você já pode avançar nos primeiros relatórios usando seu próprio material, tendo já visto o resumo estatístico e um pouco de manipulação de tabelas.

Recomendo fortemente, mais uma vez, que você dê uma olhada nas referências apresentadas no 'Para ler mais'. Ali estarão links de várias fontes com as quais você poderá explorar os processos de seleção do pandas de forma exaustiva, com um conteúdo bastante didático.

Dito isso, vejo vocês na próxima aula. Um grande abraço!

-----

**Para ler mais:**

- **[23 Efficient Ways of Subsetting a pandas DataFrame - Towards Data Science](https://towardsdatascience.com/23-efficient-ways-of-subsetting-a-pandas-dataframe-6264b8000a77)**
- **[Selecting rows in pandas DataFrame based on conditions - GeeksforGeeks](https://www.geeksforgeeks.org/selecting-rows-in-pandas-dataframe-based-on-conditions/)**
- **[Decisões e Seleção — Como pensar como um Cientista da Computação: Edição Interativa em Python](https://panda.ime.usp.br/pensepy/static/pensepy/06-Selecao/selecao.html)**
- **[A comprehensive guide to mastering data analysis with pandas - Dunder Data](https://www.dunderdata.com/master-data-analysis-with-python)**
- **[Indexing and selecting data — pandas 1.3.2 documentation](https://pandas.pydata.org/pandas-docs/stable/user_guide/indexing.html)**
- **[Noções básicas sobre notação de fatia - QAStack](https://qastack.com.br/programming/509211/understanding-slice-notation)**
- **[Selecionando várias colunas em um dataframe do pandas - QAStack](https://qastack.com.br/programming/11285613/selecting-multiple-columns-in-a-pandas-dataframe)**
- **[5 Essential Pandas Tips For Easier Data Manipulation - Towards Data Science](https://towardsdatascience.com/5-essential-pandas-tips-for-easier-data-manipulation-4c2968d37a79)**
- **[pandas.DataFrame.loc — pandas 1.3.2 documentation](https://pandas.pydata.org/docs/reference/api/pandas.DataFrame.loc.html?highlight=loc#pandas.DataFrame.loc)**
- **[Qual a diferença entre iloc, ix e loc? - QAStack](https://qastack.com.br/programming/31593201/how-are-iloc-ix-and-loc-different)**
- **[Pandas loc vs iloc | Delft Stack](https://www.delftstack.com/pt/howto/python-pandas/pandas-loc-vs-iloc-python/)**
- **[loc vs iloc in Pandas and Python - Towards Data Science](https://towardsdatascience.com/loc-vs-iloc-in-pandas-92fc125ed8eb)**


