sexta-feira, 24 de julho de 2020

Selecionando colunas com métodos do Pandas

A maioria dos códigos que utilizam a biblioteca Pandas ao selecionar uma coluna fazem uso do operador de índice. Em contrapartida é interessante saber que a biblioteca disponibiliza métodos para a mesma tarefa. Os métodos mais utilizados são select_dtypes() e filter().
Esses métodos devem ser utilizados para demandas diferentes. Se você deseja selecionar colunas pelo seu tipo, o método ideal é o select_dtypes() e se precisa selecionar pelo nome o método é o filter(). Nesse tutorial vamos aprender como utilizar esses métodos.

Como selecionar colunas com métodos da biblioteca Pandas

Chamando o método select_dtypes(), passando para o parâmetro include o valor 'O', sinalizamos para o método que queremos selecionar todas as colunas do tipo object.

>>> import pandas as pd
>>> filmes = pd.read_csv('filmes.csv')
>>> filmes.select_dtypes(include='O')
                  titulo_original  ... data_exibicao
0                  PREÇO DA PAZ O  ...     06/jul/12
1                     CARTOMANTEA  ...     13/jul/04
2            BLACK & WHITE VOL. 9  ...    26/09/2007
3                        THE GURU  ...    16/12/2002
4                  QUIET AMERICAN  ...     15/jan/03
...                           ...  ...           ...
9257                 ROCK OF AGES  ...     09/jul/20
9258                   THE MATRIX  ...     25/nov/19
9259               MILITARY WIVES  ...    14/02/2020
9260  ROBERTO CARLOS EM JERUSALÉM  ...    20/12/2019
9261                       O POÇO  ...    18/10/2019

[9262 rows x 6 columns]

Se você quiser seleciona todas as colunas com números, podemos passar o valor 'number' para o parâmetro include.

>>> filmes.select_dtypes(include='number')
      indice  codigo_obra  ano_producao
0          0        15639        2003.0
1          1         7603        2002.0
2          2        26453        2005.0
3          3        17284        2002.0
4          4         4806        2002.0
...      ...          ...           ...
9257    9257     16001794        2012.0
9258    9258     15000966        1999.0
9259    9259     19002684        2019.0
9260    9260       609762        2011.0
9261    9261     19005137        2019.0

[9262 rows x 3 columns]

É possível selecionar mais de um tipo de dados de uma vez. Se quisermos selecionar colunas com números inteiros e strings, passamos uma lista para o parâmetro include:

>>> filmes.select_dtypes(include=['int64','object'])
      indice  codigo_obra  ...     cnpj_requerente data_exibicao
0          0        15639  ...  00.568.159/0001-07     06/jul/12
1          1         7603  ...  03.599.148/0001-82     13/jul/04
2          2        26453  ...  02.341.697/0001-90    26/09/2007
3          3        17284  ...  27.654.722/0001-16    16/12/2002
4          4         4806  ...  00.979.601/0001-98     15/jan/03
...      ...          ...  ...                 ...           ...
9257    9257     16001794  ...  33.015.827/0001-28     09/jul/20
9258    9258     15000966  ...  33.015.827/0001-28     25/nov/19
9259    9259     19002684  ...  02.668.665/0001-01    14/02/2020
9260    9260       609762  ...  15.372.472/0001-42    20/12/2019
9261    9261     19005137  ...      408.504.318-83    18/10/2019

[9262 rows x 8 columns]

Obs: 'O' e 'object' se referem a strings.
E se quiséssemos selecionar todas as colunas e deixar de lado apenas um tipo de dado? Nesse caso usaríamos o parâmetro exclude. A sua utilização é bem simples, passamos apenas o tipo de dados que não queremos. Desse modo o método retornará todas as colunas, com exceção das colunas com o tipo de dado passado para o parâmetro exclude. Esse método também aceita uma lista com os tipos de dados que não queremos selecionar.

>>> filmes.select_dtypes(exclude=['int64', 'float64'])
                  titulo_original  ... data_exibicao
0                  PREÇO DA PAZ O  ...     06/jul/12
1                     CARTOMANTEA  ...     13/jul/04
2            BLACK & WHITE VOL. 9  ...    26/09/2007
3                        THE GURU  ...    16/12/2002
4                  QUIET AMERICAN  ...     15/jan/03
...                           ...  ...           ...
9257                 ROCK OF AGES  ...     09/jul/20
9258                   THE MATRIX  ...     25/nov/19
9259               MILITARY WIVES  ...    14/02/2020
9260  ROBERTO CARLOS EM JERUSALÉM  ...    20/12/2019
9261                       O POÇO  ...    18/10/2019

[9262 rows x 6 columns]

Outro método utilizado para selecionar colunas é o método filter(). Esse método retorna colunas que os nomes contenham a string passada ao parâmetro like. Assim a string não precisa ser exata ao nome da coluna, basta que o rótulo tenha a string no começo, no meio ou no final. E se várias colunas tiverem a string, o método retornará todas elas.

>>> import pandas as pd
>>> filmes = pd.read_csv('filmes.csv')
>>> filmes.filter(like='cnpj')
         cnpj_requerente
0     00.568.159/0001-07
1     03.599.148/0001-82
2     02.341.697/0001-90
3     27.654.722/0001-16
4     00.979.601/0001-98
...                  ...
9257  33.015.827/0001-28
9258  33.015.827/0001-28
9259  02.668.665/0001-01
9260  15.372.472/0001-42
9261      408.504.318-83

[9262 rows x 1 columns]

Nesse exemplo, não foi usado o nome exato da coluna, apenas uma parte (cnpj), e mesmo assim a coluna cnpj_requerente foi selecionada. No dataframe filmes, só existe uma coluna que tem a string cnpj, por isso o método retornou apenas uma coluna. Outro exemplo é passar a string 'titulo' para o parâmetro like. Como o dataframe possui duas colunas com a string 'titulo' (titulo_brasil e titulo_oroginal), o método filter() retornará duas colunas.

>>> filmes.filter(like='titulo')
                  titulo_original                titulo_brasil
0                  PREÇO DA PAZ O               PREÇO DA PAZ O
1                     CARTOMANTEA                  CARTOMANTEA
2            BLACK & WHITE VOL. 9         BLACK & WHITE VOL. 9
3                        THE GURU               O GURU DO SEXO
4                  QUIET AMERICAN        O AMERICANO TRANQUILO
...                           ...                          ...
9257                 ROCK OF AGES        ROCK OF AGES: O FILME
9258                   THE MATRIX                       MATRIX
9259               MILITARY WIVES               MILITARY WIVES
9260  ROBERTO CARLOS EM JERUSALÉM  ROBERTO CARLOS EM JERUSALÉM
9261                       O POÇO                       O POÇO

[9262 rows x 2 columns]

Outro parâmetro interessante do método filter() é o items. Com esse parâmetro podemos passar o nome das colunas que queremos. O parâmetro aceita uma lista com os valores.

>>> colunas = [
... 'diretor',
... 'indice'
... ]
>>> filmes.filter(items=colunas)
                                 diretor  indice
0     PAULO DE TARSO DE CARVALHO MORELLI       0
1         WAGNER DE ASSIS E PABLO URANGA       1
2              LENILDO MAURICIO DA SILVA       2
3                            DAISY MAYER       3
4                          PHILLIP NOYCE       4
...                                  ...     ...
9257                       ADAM SHANKMAN    9257
9258       LANA WACHOWSKI ANDY WACHOWSKI    9258
9259                      PETER CATTANEO    9259
9260    MARIO HUMBERTO MEIRELLES MOREIRA    9260
9261               ANDRE BORELLI MARTINS    9261

[9262 rows x 2 columns]

Selecionando múltiplas colunas de um dataframe com Pandas

Para selecionar uma única coluna passamos o nome da coluna como um índice do dataframe. Já vimos exemplos de como fazer isso nos tutoriais passados. Quando estamos trabalhando com um dataframe é possível que nem todos os dados que estejam ali nos interessem. Podemos resolver isso selecionando as colunas que vamos utilizar.
Nesse post vamos aprender a como selecionar duas colunas do dataframe filmes.csv.

Como selecionar duas colunas de um dataframe

Primeiro vamos importar o dataframe para uma variável. E depois criar uma lista com os nomes das colunas que pretendemos trabalhar:

>>> import pandas as pd
>>> filmes = pd.read_csv('filmes.csv')
>>> titulos = filmes[
... [
... 'titulo_original',
... 'titulo_brasil'
... ]
... ]
>>> titulos.head()
        titulo_original          titulo_brasil
0        PREÇO DA PAZ O         PREÇO DA PAZ O
1           CARTOMANTEA            CARTOMANTEA
2  BLACK & WHITE VOL. 9   BLACK & WHITE VOL. 9
3              THE GURU         O GURU DO SEXO
4        QUIET AMERICAN  O AMERICANO TRANQUILO

Em algumas situações é preciso selecionar colunas de um dataframe. Utilizando índice o resultado pode ser uma série ou um dataframe. Quando passamos, como índice, uma lista com um único item, o resultado será um dataframe. E passando uma string o resultado será uma série.

>>> type(filmes[['titulo_original']])
<class 'pandas.core.frame.DataFrame'>

>>> type(filmes['titulo_original'])
<class 'pandas.core.series.Series'>

Uma alternativa ao índice, para selecionar colunas, é o atributo loc. Com esse atributo precisamos selecionar as linhas e passar o nome da coluna que queremos selecionar. Usaremos o seletor de dois pontos para selecionar todas as linhas. Se quisermos um dataframe passamos o nome como uma lista e para série passamos uma string:

>>> type(filmes.loc[:, ['titulo_brasil']])
<class 'pandas.core.frame.DataFrame'>

>>> type(filmes.loc[:, 'titulo_brasil'])
<class 'pandas.core.series.Series'>

Como funciona…

Utilizando o operador de índice temos bastante flexibilidade. Com ele podemos utilizar diferentes objetos. Quando passamos uma lista é retornado um dataframe com todas as colunas passadas na lista. Uma coisa interessante é que o novo dataframe respeita a ordem da lista, ou seja, se queremos mudar a posição de uma coluna podemos fazer isso trocando a ordem dos nomes na lista. Se passarmos uma string recebemos uma série.
No Segundo exemplo, vimos como podemos criar um dataframe com uma única coluna a partir de um dataframe. O mesmo acontece com a série.
No terceiro exemplo, aprendemos como criar uma série e um dataframe com o atributo loc.

Tem mais...

Um problema que utilizar o operador de índice pode causar é o de legibilidade. Isso acontece quando passamos uma lista muito longa. Para resolver esse problema podemos criar uma variável do tipo lista:

>>> colunas = [
... 'titulo_brasil',
... 'titulo_original'
... ]
>>> titulos = filmes[colunas]
>>> titulos
                    titulo_brasil              titulo_original
0                  PREÇO DA PAZ O               PREÇO DA PAZ O
1                     CARTOMANTEA                  CARTOMANTEA
2            BLACK & WHITE VOL. 9         BLACK & WHITE VOL. 9
3                  O GURU DO SEXO                     THE GURU
4           O AMERICANO TRANQUILO               QUIET AMERICAN
...                           ...                          ...
9257        ROCK OF AGES: O FILME                 ROCK OF AGES
9258                       MATRIX                   THE MATRIX
9259               MILITARY WIVES               MILITARY WIVES
9260  ROBERTO CARLOS EM JERUSALÉM  ROBERTO CARLOS EM JERUSALÉM
9261                       O POÇO                       O POÇO

[9262 rows x 2 columns]
>>> filmes.info()
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 9262 entries, 0 to 9261
Data columns (total 9 columns):
 #   Column                   Non-Null Count  Dtype
---  ------                   --------------  -----
 0   indice                   9262 non-null   int64
 1   codigo_obra              9262 non-null   int64
 2   titulo_original          9262 non-null   object
 3   titulo_brasil            9262 non-null   object
 4   ano_producao             9259 non-null   float64
 5   diretor                  9262 non-null   object
 6   razao_social_requerente  9262 non-null   object
 7   cnpj_requerente          9262 non-null   object
 8   data_exibicao            9262 non-null   object
dtypes: float64(1), int64(2), object(6)
memory usage: 434.2+ KB

Com o exemplo acima podemos perceber que a ordem das colunas foi alterada. A causa disso é a ordem em que os nomes das colunas foram colocados na lista.

quinta-feira, 23 de julho de 2020

Criando e deletando colunas no Pandas

Quando trabalhamos com dados em algum momento vamos precisar criar uma coluna para adicionar novos dados. Na grande maioria dos casos essa nova coluna será criada num dataframe já existente. Com a biblioteca Pandas podemos criar colunas de maneiras diferentes.
Nesse post, vamos criar novas colunas com o método assign() e deletar colunas, que não vamos precisar, com o método drop().

Como criar colunas com Pandas

Para criar uma nova coluna vamos atribuir um valor a um índice. É importante lembra que não vamos criar um dataframe novo, mas sim modificando o atual. Quando atribuir um valor a coluna, o valor passado será usado para todos os elementos da coluna. Vamos criar uma coluna indicando se já vimos o filme. Por padrão as novas colunas são adicionadas no final.

>>> import pandas as pd
>>> filmes = pd.read_csv('filmes.csv')
>>> filmes['assistido'] = 0

Mesmo o exemplo acima funcionando e sendo bastante comum, ainda podemos usar o método assign(). Usando esse método um novo dataframe será criado com uma coluna a mais. O método usa o nome do parâmetro como o novo nome da coluna, então o novo nome deve ser um nome valido para um parâmetro.

>>> filmes = filmes.drop(columns='assistido')
>>> filmes.assign(assistido = 0)
      indice  codigo_obra  ... data_exibicao assistido
0          0        15639  ...     06/jul/12         0
1          1         7603  ...     13/jul/04         0
2          2        26453  ...    26/09/2007         0
3          3        17284  ...    16/12/2002         0
4          4         4806  ...     15/jan/03         0
...      ...          ...  ...           ...       ...
9257    9257     16001794  ...     09/jul/20         0
9258    9258     15000966  ...     25/nov/19         0
9259    9259     19002684  ...    14/02/2020         0
9260    9260       609762  ...    20/12/2019         0
9261    9261     19005137  ...    18/10/2019         0

[9262 rows x 10 columns]

Para remover uma coluna vamos usar o método drop(). O método drop() recebe o nome da coluna que queremos excluir do dataframe através do parâmetro columns. Veja um exemplo:

>>> filmes.drop(columns = 'assistido')

Repare que o método drop() cria um novo dataframe, assim como o método assign().
Uma alternativa ao método drop() é com a declaração del.

    del filmes[‘diretor’]

Tem mais...

Se você quiser adicionar uma coluna entre outras já existentes, o método que você deve utilizar é o insert(). Esse método recebe três parâmetros: o primeiro deve ser um inteiro com a posição da nova coluna; o segundo, o nome da nova coluna; e o terceiro os valores da coluna.

>>> filmes.insert(
... loc=6,
... column='nova',
... value=42
... )
>>> filmes.info()
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 9262 entries, 0 to 9261
Data columns (total 11 columns):
 #   Column                   Non-Null Count  Dtype
---  ------                   --------------  -----
 0   indice                   9262 non-null   int64
 1   codigo_obra              9262 non-null   int64
 2   titulo_original          9262 non-null   object
 3   titulo_brasil            9262 non-null   object
 4   ano_producao             9259 non-null   float64
 5   diretor                  9262 non-null   object
 6   nova                     9262 non-null   int64
 7   razao_social_requerente  9262 non-null   object
 8   cnpj_requerente          9262 non-null   object
 9   data_exibicao            9262 non-null   object
 10  assistido                9262 non-null   object
dtypes: float64(1), int64(3), object(7)
memory usage: 542.8+ KB

Nesse exemplo, adicionamos uma coluna depois da coluna ‘diretor’, na posição seis (lembre-se que o índice começa em zero). E adicionamos o valor quarenta e dois para todos os elementos dessa coluna. O parâmetro value aceita números inteiros, séries ou arrays.

quarta-feira, 22 de julho de 2020

Renomeando o nome de uma coluna com Pandas

Quando trabalhamos com dataframe é muito comum a renomeação das colunas. Renomear as coluna é importante, principalmente com idiomas que usam caracteres especiais, para que os nomes das colunas possam ser usados como nomes de atributos. Com isso em mente os nomes não podem começar com números e devem ser alfanuméricos com letras maiúsculas ou minúsculas, o underline também é um caractere válido. Uma boa escolha de nove descreve o conteúdo da coluna e não entra em conflito com os atributos, já existentes, dos dataframe e séries.
Nesse post vamos aprender a renomear os nomes das colunas dos dataframe e séries do Pandas. Com a renomeação dos nomes procuramos deixar o código mais organizado e de fácil compreensão. Uma escolha errada de nome para uma coluna pode dificultar o seu acesso.

Como fazer...

Nesse exemplo vamos renomear os nomes das colunas do dataframe com o método rename(). O método rename() aceita um dicionário com os nomes velhos e novos da coluna.

>>> import pandas as pd
>>> filmes = pd.read_csv('filmes.csv', encoding='latin-1')
>>> n_nomes = {
... 'Codigo da obra':'codigo_obra',
... 'Titulo Original':'titulo_original',
... 'Titulo no Brasil':'titulo_brasil',
... 'Ano de producão':'ano_producao',
... 'Diretor':'diretor',
... 'Razão Social do Requerente':'razao_social_requerente',
... 'CNPJ Requerente':'cnpj_requerente',
... 'Data de exibicão':'data_exibicao'}
>>> filmes.rename(columns=n_nomes).head()
   codigo_obra       titulo_original  ...     cnpj_requerente  data_exibicao
0        15639        PREÇO DA PAZ O  ...  00.568.159/0001-07      06/jul/12
1         7603           CARTOMANTEA  ...  03.599.148/0001-82      13/jul/04
2        26453  BLACK & WHITE VOL. 9  ...  02.341.697/0001-90     26/09/2007
3        17284              THE GURU  ...  27.654.722/0001-16     16/12/2002
4         4806        QUIET AMERICAN  ...  00.979.601/0001-98      15/jan/03

[5 rows x 8 columns]

Como funciona...

Com o método rename() podemos renomear os nomes das colunas. Os novos nomes das colunas são passados para o parâmetro colunms como um dicionário com os nomes antigos e os novos.

Encadeando métodos das séries do Pandas

Na linguagem python é possível chamar métodos usando o acesso a atributos. As variáveis apontam para objetos e os atributos e métodos retornam mais objetos. Assim podemos fazer chamadas sequenciais de métodos usando atributos. Pandas é uma biblioteca que faz bom uso dessa programação de fluxo. Muitos métodos e atributos criam séries e dataframes, que por sua vez podem criar mais séries e dataframes. E desses objetos mais métodos e atributos podem ser chamados.
Como exemplo de encadeamento de métodos, vamos usar a frase: Uma pessoa vai ao restaurante comer costelas, volta pra casa, lava o carro e depois assiste TV.
Uma forma de codificar essa frase em python:

(pessoa.ir('Restaurante')
.pede('Costela')
.come('Costela')
.ir('Casa')
.lavar('Carro')
.assistir('TV')
)

Nesse exemplo, a pessoa é uma instância de uma classe que pode chamar métodos. E cada método pode criar outra instância, desse jeito o encedeamento ocorre. No exemplo acima, o argumento passado para o método define como o método deve ser executado.
Nesse post vamos aprender como o encadeamento funciona nas séries do Pandas.

Como fazer...

Primeiro vamos extrair uma coluna do dataset e encadear métodos da série:

>>> import pandas as pd
>>> filmes = pd.read_csv('filmes.csv', encoding='latin-1')
>>> diretor = filmes.Diretor
>>> diretor.value_counts().head(5)
LENILDO MAURICIO DA SILVA    218
JULIANO COSTA BENDAZOLI       69
JOSE ANTONIO GASPAR RAMOS     39
ROGER LEMOS                   26
LENILDO MAURÍCIO DA SILVA     22
Name: Diretor, dtype: int64

Nesse exemplo, chamamos o método value_counts(). Esse método retorna uma série contendo os elementos da série progenitora com a quantidade de vezes que o valor aparece na série. E logo em seguida chamamos o método head(5), que cria uma nova série com os cinco primeiros elementos retornados pelo método value_counts(). Pode não parecer mais a cada chamada de método criamos uma série nova.
Uma consequência do encadeamento de métodos e atributos é a dificuldade na hora de fazer a depuração. Isso acontece porque nenhum dos resultados dos métodos é guardado numa variável. Num encadeamento muito longo fica difícil encontrar o local do erro, se acontecer algum (e vai.). Uma dica para minimizar esse tipo de erro é colocar o resultado da chamada do método numa variável separada e depurar o seu código linha a linha.

Operações com séries do Pandas

A linguagem python nos permite fazer operações básicas com números e objetos atraves dos operadores. Com esses operadores somos capazes de manipular objetos. Um exemplo é o operador '+', com ele podemos somar dois inteiros e receber o resultado:

>>> 3 + 7 # Soma os dois números
10

Podemos usar operadores para manipular as séries e os dataframe do Pandas. As séries e os dataframe tem suporte a muitos dos operadores da linguagem python. Quando usamos um operador com uma série ou um dataframe vamos ter como resultado uma série ou um dataframe. Nesse post vamos apresentar alguns operadores que podemos usar com séries e dataframes. Ao usar esses operadores teremos como resultado séries com valores diferentes dos seus progenitores.

Como fazer isso...

O dataset que vamos usar nos exemplos abaixo pode ser baixado aqui.
Primeiro vamos começar com um operador fácil, o operador de soma. Utilizar esse operador com uma série e um inteiro irá criar uma nova série com cada elemento da série acrescentado do número inteiro. Veja um exemplo:

>>> import pandas as pd
>>> data = pd.read_csv('data.tsv', sep='\t')
>>> classif_media = data.averageRating
>>> classif_media
0          5.7
1          6.1
2          6.5
3          6.2
4          6.1
          ...
1056047    7.2
1056048    6.6
1056049    5.9
1056050    6.9
1056051    7.3
Name: averageRating, Length: 1056052, dtype: float64
>>> classif_media + 1
0          6.7
1          7.1
2          7.5
3          7.2
4          7.1
          ...
1056047    8.2
1056048    7.6
1056049    6.9
1056050    7.9
1056051    8.3
Name: averageRating, Length: 1056052, dtype: float64

As operações de divisão, multiplicação, exponenciação e subtração seguem a mesma lógica. Veja os exemplos abaixo:

>>> classif_media / 2
0          2.85
1          3.05
2          3.25
3          3.10
4          3.05
           ...
1056047    3.60
1056048    3.30
1056049    2.95
1056050    3.45
1056051    3.65
Name: averageRating, Length: 1056052, dtype: float64
>>> classif_media * 2
0          11.4
1          12.2
2          13.0
3          12.4
4          12.2
           ...
1056047    14.4
1056048    13.2
1056049    11.8
1056050    13.8
1056051    14.6
Name: averageRating, Length: 1056052, dtype: float64
>>> classif_media ** 2
0          32.49
1          37.21
2          42.25
3          38.44
4          37.21
           ...
1056047    51.84
1056048    43.56
1056049    34.81
1056050    47.61
1056051    53.29
Name: averageRating, Length: 1056052, dtype: float64
>>> classif_media - 2
0          3.7
1          4.1
2          4.5
3          4.2
4          4.1
          ...
1056047    5.2
1056048    4.6
1056049    3.9
1056050    4.9
1056051    5.3
Name: averageRating, Length: 1056052, dtype: float64

Para fazer a divisão exata, o que vai gerar um float, use duas barras. O operador módulo também é suportado pelas séries do Pandas.

>>> classif_media // 3
0          1.0
1          2.0
2          2.0
3          2.0
4          2.0
          ...
1056047    2.0
1056048    2.0
1056049    1.0
1056050    2.0
1056051    2.0
Name: averageRating, Length: 1056052, dtype: float64
>>> classif_media % 3
0          2.7
1          0.1
2          0.5
3          0.2
4          0.1
          ...
1056047    1.2
1056048    0.6
1056049    2.9
1056050    0.9
1056051    1.3
Name: averageRating, Length: 1056052, dtype: float64

Outros operadores válidos, para serem usados com as séries do Pandas, são os de comparação (>, <, ==, >=, <=, !=). Utilizando esses operadores a saída será uma série com valores booleanos. A comparação será feita entre o valor passado e cada elemento da série. Veja um exemplo:

>>> classif_media > 6
0          False
1           True
2           True
3           True
4           True
           ...
1056047     True
1056048     True
1056049    False
1056050     True
1056051     True
Name: averageRating, Length: 1056052, dtype: bool

O valor do primeiro elemento da série é False, isso porque o primeiro elemento da série classif_media é menor ou igual a seis. O segundo é True pois o valor do segundo elemento da série classif_media é maior que seis.
Podemos usar os operadores de comparação com strings. Para esse exemplo vamos utilizar o dataset dos tutoriais passados. Veja um exemplo:

>>> filmes = pd.read_csv('filmes.csv', encoding='latin-1')
>>> diretor = filmes.Diretor
>>> diretor
0       PAULO DE TARSO DE CARVALHO MORELLI
1           WAGNER DE ASSIS E PABLO URANGA
2                LENILDO MAURICIO DA SILVA
3                              DAISY MAYER
4                            PHILLIP NOYCE
                       ...
9257                         ADAM SHANKMAN
9258         LANA WACHOWSKI ANDY WACHOWSKI
9259                        PETER CATTANEO
9260      MARIO HUMBERTO MEIRELLES MOREIRA
9261                 ANDRE BORELLI MARTINS
Name: Diretor, Length: 9262, dtype: object
>>> diretor == 'DAISY MAYER'
0       False
1       False
2       False
3        True
4       False
        ...
9257    False
9258    False
9259    False
9260    False
9261    False
Name: Diretor, Length: 9262, dtype: bool

Como funciona...

Nos exemplos acima os operadores são usados em cada elemento da série individualmente. Se fossemos fazer isso sem a biblioteca Pandas precisaríamos de um loop para cada elemento. Mas graças ao Pandas não precisamos.
Em cada um dos exemplos é retornada uma série com os mesmos índices mais com novos valores.

Tem mais...

Para cada operador existe um método que faz exatamente a mesma coisa. Veja um exemplo com a divisão:

>>> classif_media / 2
0          2.85
1          3.05
2          3.25
3          3.10
4          3.05
           ...
1056047    3.60
1056048    3.30
1056049    2.95
1056050    3.45
1056051    3.65
Name: averageRating, Length: 1056052, dtype: float64
>>> classif_media.div(2)
0          2.85
1          3.05
2          3.25
3          3.10
4          3.05
           ...
1056047    3.60
1056048    3.30
1056049    2.95
1056050    3.45
1056051    3.65
Name: averageRating, Length: 1056052, dtype: float64

Abaixo temos uma tabela com os operadores e seus métodos correspondentes:

Grupo de operadores Operadores Métodos
Aritmético + , - , * , / , // , % , ** .add , .sub , .mul , .div , .floordiv , .mod , .pow
Comparação < , > , <= , >= , == , != .lt , .gt , .le , .ge , .eq , .ne

terça-feira, 21 de julho de 2020

Como chamar métodos de uma série do Pandas

Quando estamos trabalhando com a biblioteca Pandas é normal ficar alterando entre séries e dataframe. Fazer uso dos métodos de uma série é uma ótima maneira de extrair o máximo da biblioteca Pandas.
Dataframe e séries possuem muitos métodos e atributos. Para descobrirmos alguns desses métodos e atributos podemos usar a função build-in do python dir. No exemplo abaixo vamos mostra a quantidade de métodos que as séries e os dataframe têm em comum. Uma coisa para se notar é que as séries e os dataframe têm um grande número de atributos e métodos com nomes iguais.

>>> import pandas as pd
>>> s_atr_metodos = set(dir(pd.Series))
>>> len(s_atr_metodos)
433 # número de métodos e atributos de uma série
>>> df_atr_metodos = set(dir(pd.DataFrame))
>>> len(df_atr_metodos)
430 # número de métodos e atributos de um dataframe
>>> len(s_atr_metodos & df_atr_metodos)
377 # Métodos e atributos em comum

Com esse exemplo percebemos que existem muitos atributos e métodos na biblioteca Pandas. Você deve estar pensando que são muitos para aprender, mas não se preocupe. Os programadores mais experientes só usam alguns desses métodos e atributos.
Nos tutoriais, que viram, vamos aprender os métodos e atributos das séries mais utilizados e poderosos. Como ficou claro no exemplo acima a maioria desses métodos e atributos tem um correspondente para os DataFrame.

Como fazer isso...

Agora vamos selecionar duas séries de tipos diferentes de um dataset. A coluna 'Diretor' é formada pelo tipo de dado object - Esse tipo de dado é utilizado, em sua maioria, para representar strings. E a coluna 'Codigo da obra'. Essa coluna é formada por números inteiros (int64). Veja o exemplo abaixo:

>>> import pandas as pd
>>> filmes = pd.read_csv('filmes.csv', encoding='latin-1')
>>> diretor = filmes['Diretor']
>>> cod = filmes['Codigo da obra']
>>> diretor.dtype
dtype('O')
>>> cod.dtype
dtype('int64')

Para saber quais são os cinco primeiros elementos de uma série usamos o método head. Se for preciso um número maior de elementos isso pode ser arranjado com parâmetros opcionais. Outro método, para visualizar dados de uma série, é o sample. Com esse método é possível pegar amostras de toda a série. Veja como utilizar esses métodos:

>>> diretor.head()
0    PAULO DE TARSO DE CARVALHO MORELLI
1        WAGNER DE ASSIS E PABLO URANGA
2             LENILDO MAURICIO DA SILVA
3                           DAISY MAYER
4                         PHILLIP NOYCE
Name: Diretor, dtype: object
>>> diretor.sample(n=6, random_state=32)
3601                          JEAN-FRANÇOIS RICHET
1663                                ETHAN MANIQUIS
4897                               DAVID BLAUSTEIN
3710    LUIZ DE FRANCA GUILHERME DE QUEIROGA FILHO
1641                                 ANTOINE FUQUA
2611                                       MAT ASS
Name: Diretor, dtype: object

O método sample() recebeu dois parâmetros. O primeiro (n) sinaliza o numero de elementos que queremos e o random_state define a semente que o método vai utilizar para gerar os números aleatórios.
Sabendo o tipo de dado de uma série, sabemos qual é a função que mais vamos utilizar. Um exemplo disso é o método value_counts(). Esse método retorna uma série contendo o nome dos elementos e quantas vezes esse valor se repete. No exemplo abaixo, vemos que o valor 'ROGER LEMOS' aparece vinte e seis vezes na série, enquanto 'DESIREE AKHAVAN' aparece uma vez apenas.

>>> diretor.value_counts()
LENILDO MAURICIO DA SILVA    218
JULIANO COSTA BENDAZOLI       69
JOSE ANTONIO GASPAR RAMOS     39
ROGER LEMOS                   26
LENILDO MAURÍCIO DA SILVA     22
                            ...
HUGO REYNALDO MATTAR           1
DESIREE AKHAVAN                1
CHARLES FERGUSON               1
JORGE PAIXÃO DA COSTA          1
JESUS GARCES LAMBERT           1
Name: Diretor, Length: 4976, dtype: int64

Embora esse método seja mais utilizado com séries com dados do tipo objeto, você também pode usa-la com séries com dados numéricos.
Se você precisar saber o tamanho de uma série a biblioteca Pandas fornece algumas formas de fazer isso, como o atributo size, shape e o método count(). E ainda temos a função interna do python len(). Veja como usar esses métodos:

>>> diretor.size
9262
>>> diretor.shape
(9262,)
>>> len(diretor)
9262
>>> diretor.count()
9262

O método count() retorna o número de elementos com valores, os elementos NaN não são contabilizados.
E ainda temos o método unique(). Esse método retorna todos os elementos únicos da série, deixando de lado os valores duplicados.

>>> diretor.unique()
array(['PAULO DE TARSO DE CARVALHO MORELLI',
       'WAGNER DE ASSIS E PABLO URANGA', 'LENILDO MAURICIO DA SILVA', ...,
       'ÁLVARO DELGADO-APARICIO L.', 'KIM HONG-SUN',
       'MARIO HUMBERTO MEIRELLES MOREIRA'], dtype=object)

As funções de estatísticas de uma série são: min(), que retorna o menor valor da série; max(), retorna o maior valor; mean(), que retorna a média entre os valores da série; e median(), que retorna a mediana.

>>> cod.min()
1
>>> cod.max()
20002501
>>> cod.mean()
10534938.192291081
>>> cod.median()
15004498.0

Se você esta com um pouco de pressa e precisa saber as informações do exemplo anterior com um método só. Você pode usar o método describe(). Com esse método você vai obter as informações básicas de estatística da série. Um exemplo:

>>> cod.describe()
count    9.262000e+03
mean     1.053494e+07
std      7.714715e+06
min      1.000000e+00
25%      4.165462e+05
50%      1.500450e+07
75%      1.600608e+07
max      2.000250e+07
Name: Codigo da obra, dtype: float64

Chamando o método quantile() obtemos o quantil de dados numéricos. Se passarmos um valor escalar como argumento, vamos receber uma saída escalar, e se passarmos uma lista vamos receber uma série.

>>> cod.quantile(0.3)
630214.2
>>> cod.quantile(
... [0.1, 0.2, 0.3, 0.4, 0.5]
... )
0.1       15196.1
0.2      278800.6
0.3      630214.2
0.4    14026379.0
0.5    15004498.0
Name: Codigo da obra, dtype: float64

Com o método count() podemos saber a quantidade de elementos de uma série que tem um valor definido. E se quiséssemos saber os valores que estão faltando? Nesse caso usaríamos o método isna(). Esse método retorna uma série com os valores True ou False para cada elemento de uma série. Por exemplo, se o primeiro elemento da série não tiver um valor o primeiro elemento da série, retornada pelo método isna(), vai ser True e False caso o elemento tenha um valor definido. E isso se repete até o último elemento das duas séries.

>>> diretor.isna()
0       False
1       False
2       False
3       False
4       False
        ...
9257    False
9258    False
9259    False
9260    False
9261    False
Name: Diretor, Length: 9262, dtype: bool

Nesse exemplo, o resultado do método isna() foi uma série com todos os valores False, isso pois a série que usamos não tem nenhum valor faltando.
Agora vamos supor que a série que usamos no exemplo anterior tivesse alguns valores faltando e quiséssemos preencher esse espaço vazio com o valor ‘Sem diretor’. Nesse caso usaríamos o método fillna(). Esse método preenche os valores vazios da série com o valor que recebe. Um exemplo de como fazer:

>>> diretor.fillna('Sem diretor')
0       PAULO DE TARSO DE CARVALHO MORELLI
1           WAGNER DE ASSIS E PABLO URANGA
2                LENILDO MAURICIO DA SILVA
3                              DAISY MAYER
4                            PHILLIP NOYCE
                       ...
9257                         ADAM SHANKMAN
9258         LANA WACHOWSKI ANDY WACHOWSKI
9259                        PETER CATTANEO
9260      MARIO HUMBERTO MEIRELLES MOREIRA
9261                 ANDRE BORELLI MARTINS
Name: Diretor, Length: 9262, dtype: object

Outra possibilidade é que você não queira adicionar um valor onde está faltando, mas sim remover esses elementos vazios. Nesse caso faríamos uso do método dropna(). Esse método remove todos os elementos vazios da série. Veja um exemplo de uso:

>>> diretor.dropna()
0       PAULO DE TARSO DE CARVALHO MORELLI
1           WAGNER DE ASSIS E PABLO URANGA
2                LENILDO MAURICIO DA SILVA
3                              DAISY MAYER
4                            PHILLIP NOYCE
                       ...
9257                         ADAM SHANKMAN
9258         LANA WACHOWSKI ANDY WACHOWSKI
9259                        PETER CATTANEO
9260      MARIO HUMBERTO MEIRELLES MOREIRA
9261                 ANDRE BORELLI MARTINS
Name: Diretor, Length: 9262, dtype: object

Nesse post aprendemos a utilizar alguns dos métodos mais utilizados na análise de dados com a biblioteca Pandas.
Os métodos que aprendemos a utilizar retornam diferentes tipos de dados.

Tem mais...

Com os exemplos que usamos, até agora nesse post, podemos saber se existem valores faltando na série observando o resultado do método count() (que retorna o número de elementos com valor) e o atributo size (que retorna o número total de elementos de uma série). Uma abordagem mais direta séria o atributo hasnans. Se tiver algum elemento sem valor, o valor do atributo será True, caso contrario será False.