Introdução ao Pandas – Series

🔻Final do artigo

O que é pandas?

Pandas é uma biblioteca do Python, de código aberto e com licença BSD, desenvolvida e mantida pelo PуDаtа Dеvеlорmеnt Tеаm. Ela fornece ferramentas de manipulação e análise estatística de dados, com capacidade de exibição gráfica, com extração de dados análogos (mas não idênticos) aos de consultas sql. [veja nesse site, sql.]

A biblioteca foi construída com Cython e, por isso, é bastante rápida. Ela se destinava inicialmente ao uso no setor financeiro para análise de séries temporiais, tendo se tornado uma ferramenta de uso comum na manipulação de dados, particularmente em data science e machine learning. Ela tem sido usada para substituir as planilhas do Excel, para processar dados sob forma tabular, importando com facilidade dados de arquivos csv ou json.

Os experimentos abaixo foram realizados no Jupyter Notebook. Você encontra nesse site um artigo sobre instalação e uso do Jupyter Notebook. As linhas de código e suas respostas, quando existirem, serão representadas da seguinte forma:

# Linhas de comentários (não serão numeradas)   
In [n]: Linha de input n
Out[n]: Output da linha n

NumPy e matplotlib

NumPy é a abreviação de Numerical Python, a biblioteca base da computação numérica em Python. Ela fornece as estruturas de dados e algoritmos necessários para a maioria das aplicações científicas e de engenharia utilizando cálculo numérico. Entre outros objetos NumPy NumPy fornece

  • o objeto multidimensional ndarray onde se pode aplicar operações vetorializadas rápidas e eficientes,
  • um conjunto de funções para cálculos elementares com vetores e matrizes,
  • ferramentas de leitura e gravação de dados,
  • operações da álgebra linear, transformada de Fourier e geração de números aleatórios,
  • interação com C e C++.

Para dados numéricos as matrizes do NumPy são armazenadas e manipuladas de modo mais eficiente do que as demais estruturas do Python. Além disso códigos escritos em linguagens de baixo nível, como C ou Fortran, podem operar diretamente nos dados armazenados com o NumPy. Por isso muitas ferramentas de computação numérica do Python usam as matrizes NumPy como um estrutura de dados primária.

matplotlib é a biblioteca Python mais popular usada para a produção de gráficos e visualização de dados. Ela pode ser usada na geração de gráficos estáticos ou animados e visualização interativa.

Pandas

O pandas se utiliza basicamente de 3 objetos de armazenamento de dados com as seguintes estuturas:

Estrutura de dados dos objetos do pandas
Nome dimensões tabela
Series 1D coluna (vetor)
DataFrame 2D tabela (matriz)
Panel 3D várias tabelas (matriz multidimensional)

As series e os dataframes são utilizados com maior frequência.

Para usar as bibliotecas dentro do código começamos com as importações

In [1]: import pandas as pd
In [2]: import numpy as np

Series

Uma series é um objeto unidimensional tipo um vetor que contém uma sequência de objetos do mesmo tipo. A essa sequência está associado um outro vetor de labels chamado de índice (index). O método básico de criação de séries é da seguinte forma:

s = pd.Series(data, index=index)

onde data pode ser um dict (um dicionário do Python), uma lista ou ndarray do numPy ou um escalar. index é uma lista de índices que, se omitida, é preenchida com inteiros iniciando em 0.

In [3]: serie1 = pd.Series([-1, 9, 0, 2, 5])
Out[3]:
 0   -1
 1    9
 2    0
 3    2
 4    5

À esquerda estão listados os índices que, por default, são uma lista de inteiros começando por 0. Os valores podem ser listados com .values e os índices com .index.

In [4]: serie1.values
Out[4]: array([-1,  9,  0,  2,  5])

In [5]: serie1.index
Out[5]: RangeIndex(start=0, stop=5, step=1)

Os índices podem ser inseridos manualmente e não precisam ser inteiros. No input [8] um valor da serie é recuperado por seu índice, que é um string.

In [6]: serie2 = pd.Series([4, 7, -5, 3], index=['a', 'b', 'c', 'd'])
In [7]: serie2
Out[7]: 
a    4
b    7
c   -5
d    3
dtype: int64

In [8]: serie2['c']
Out[8]: -5

Uma série pode ser filtrada por meio de um argumento passado como outra serie booleana. Além disso operações podem ser realizadas sobre todos os elementos da série.

# O teste seguinte gera uma série de booleanos
In [9]: serie2 > 3
Out[9]: 
a     True
b     True
c    False
d    False
dtype: bool

# Essa serie de True e False filtra a serie original
In [10]: serie2[serie2 > 3]
Out[10]:
a    4
b    7
dtype: int64

# Operações podem, ser realizadas sobre todos os elementos
In [11]: serie2 * 3
Out[11]: a    12
b    21
c   -15
d     9
dtype: int64

# Numpy tem a função exponencial
In [12]: np.exp(serie2)
Out[12]:
a      54.598150
b    1096.633158
c       0.006738
d      20.085537
dtype: float64

Uma série se comporta, em muitos sentidos, como um dicionário. Uma série pode ser criada passando-se um dicionário como argumento para pd.Series().

In [13]: populacao = {
           'Sudeste': 89012240, 
           'Nordeste': 57374243,
           'Sul': 30192315,
           'Norte': 18672591,
           'Centro-Oeste':16504303
         }

In [14]: serie3 = pd.Series(populacao)

In [15]: serie3
Out[15]:
Sudeste         89012240
Nordeste        57374243
Sul             30192315
Norte           18672591
Centro-Oeste    16504303
dtype: int64 

# A ordem dos itens na série pode ser alterada fornecendo uma lista para o argumento index:
In [16]: ordem_alfabetica = ['Brasil', 'Nordeste', 'Norte', 'Centro-Oeste', 'Sudeste', 'Sul']
In [17]: serie4 = pd.Series(populacao, index=ordem_alfabetica)
In [18]: serie4
Out[18]:
Brasil               NaN
Nordeste        57374243
Norte           18672591
Centro-Oeste    16504303
Sudeste         89012240
Sul             30192315
dtype: int64

# para verificar queis valores são nulos (NaN)
In [19]: pd.isnull(serie4)
Out[19]:
Brasil           True
Nordeste        False
Norte           False
Centro-Oeste    False
Sudeste         False
Sul             False
dtype: bool

# os seguintes registros são NaN
In [20]: serie4[pd.isnull(serie4)]
Out[20]:
Brasil   NaN
dtype: float64

In [21]: serie4[pd.notnull(serie4)]
Out[20]:
Nordeste        57374243.0
Norte           18672591.0
Centro-Oeste    16504303.0
Sudeste         89012240.0
Sul             30192315.0
dtype: float64

In [21]: 'Brasil' in serie4
Out[21]: True
In [22]'USA' in serie4
Out[22] False

In [23]: serie4['USA']
Out[23]: KeyError

Como não existe no dicionário um valor para o índice ‘Brasil’ a série atribuiu o valor NaN (Not a Number para essa chave, a forma de NumPy e pandas parea indicar a ausência de um valor. O método retorna True ou False para cada item da série e pd.notnull() o seu inverso booleano. Alternativamente se pode usar o método das séries serie4.isnull().

Em diversos aspectos uma serie se parece com um dict. Por ex., podemos testar a existência de uma chave usando o comando in, como em In[21]. A tentativa de recuperar um valor com índice não existente, em In [23], gera uma exceção (um erro do Python).

Observe que uma series tem propriedades de numpy ndarray, mas é um objeto de tipo diferente. Se um ndarray é necessário use .to_numpy().

In [24]: type(serie4)
Out[24]: pandas.core.series.Series

In [25]: type(serie4.to_numpy())
Out[25]: numpy.ndarray

Series podem ser fatiadas com a notação serie[i:f] onde serão retornadas a i-ésima linha até a f-ésima, exclusive. Se i for omitido a lista se inicia em 0, se f for omitido ela termina no final.

In [26]: serie4
Out[26]:
Brasil                 NaN
Nordeste        57374243.0
Norte           18672591.0
Centro-Oeste    16504303.0
Sudeste         89012240.0
Sul             30192315.0
dtype: float64

In [27]: serie4[2:5]
Out[27]:
Norte           18672591.0
Centro-Oeste    16504303.0
Sudeste         89012240.0
dtype: float64

In [28]: serie4[:2]
Out[28]: 
Brasil             NaN
Nordeste    57374243.0
dtype: float64

In [29]: serie4[4:]
Out[29]: 
Sudeste    89012240.0
Sul        30192315.0
dtype: float64

O resultado de operações envolvendo mais de uma serie alinha os valores por chaves (como uma UNION). Valores não presentes em um dos operandos terá NaN como resultado.

In [29]: serie5 = pd.Series([2, -1, -2, 1], index=['a', 'b', 'c', 'd'])
In [29]: serie6 = pd.Series([3, 4, 7, -1], index=['e', 'c', 'b', 'f'])
Out[29]: display(serie5, serie6)
a    2
b   -1
c   -2
d    1
dtype: int64

e    3
c    4
b    7
f   -1
dtype: int64

In [29]: serie5 + serie6
Out[29]:
a    NaN
b    6.0
c    2.0
d    NaN
e    NaN
f    NaN
dtype: float64

Series possuem a propriedade name que pode ser atribuída na construção ou posteriormente com .rename().

In [30]: serie7 = pd.Series(np.random.randn(5), name='randomica')
In [31]: serie7
Out[31]:
0   -1.703662
1    1.406167
2    0.966557
3   -0.557846
4   -0.264914
Name: randomica, dtype: float64

In [32]: serie7.name
Out[32]:
'randomica'

In [33]: serie7= serie7.rename('aleatoria')
In [34]: serie7.name
Out[34]:
'aleatoria'

O nome de uma série se torna seu índice ou nome de coluna caso ela seja usada para formar um DataFrame.

Atributos e Métodos das Series

Os atributos e métodos mais comuns e úteis das Series estão listados abaixo. Para uma lista completa consulte pandas.Series: API Reference.

Atributos

Atributo Descrição
at Accesso a um valor específico em uma par linha/coluna
attrs Retorna ditionario de atributos globais da series
axes Retorna lista de labels do eixo das linhas
dtype Retorna o tipo (dtype) dos objetos armazenados
flags Lista as propriedades do objeto
hasnans Informa se existem NaNs
iat Acessa valor usando um inteiro como índice
iloc Seleciona por posição usando índice inteiro
index Retorna lita de índices
is_monotonic Booleano: True se valores crescem de forma monotônica
is_monotonic_decreasing Booleano: True se valores decrescem de forma monotônica
is_unique Booleano: True se valores na series são únicos
loc Acessa linhas e colunas por labels oo array booleano
name O nome da Series
nbytes Número de bytes nos dados armazenados
shape Retorna uma tuple com forma (dimensões) dos dados
size Número de elementos nos dados
values Retorna Series como ndarray

Métodos

Método Descrição
abs() Retorna a Series com valor absoluto para cada elemento
add(serie2) Soma a serie com serie2, elemento a elemento
add_prefix(‘prefixo’) Adiciona prefixo aos labels com string ‘prefixo’
add_suffix(‘sufixo’) Adiciona sufixo aos labels com string ‘sufixo’
agg([func, axis]) Agrega usando func sobre o eixo especificado
align(serie2) Alinha 2 objetos em seus eixos usando método especificado
all([axis, bool_only, skipna, level]) Retorna se todos os elementos são True
any([axis, bool_only, skipna, level]) Retorna se algum elemento é True
append(to_append[, ignore_index, …]) Concatena 2 ou mais Series
apply(func[, convert_dtype, args]) Aplica func sobre todos os valores da series
argmax([axis, skipna]) Retorna posição (índice inteiro) do valor mais alto da Series.
argmin([axis, skipna]) Retorna posição (índice inteiro) do menor valor da Series.
argsort([axis, kind, order]) Retorna índices inteiros que ordenam valores da Series
asfreq(freq) Converte TimeSeries para frequência especificada.
asof(where[, subset]) Retorna última linha anterores à ocorrência de NaNs antes de ‘where’
astype(dtype[, copy, errors]) Transforma objeto object para um dtype
at_time(time[, asof, axis]) Seleciona valores em determinada hora (ex., 9:30AM)
backfill([axis, inplace, limit, downcast]) Alias para DataFrame.fillna() usando method=’bfill’
between(min, max) Retorna Series booleana satisfazendo min <= series <= max.
between_time(inicio, fim) Seleciona valores com tempo entre inicio e fim
bfill([axis, inplace, limit, downcast]) Alias para DataFrame.fillna() usando method=’bfill’
clip([min, max, axis, inplace]) Inclui apenas valores no intervalo
combine(serie2, func[, fill_value]) Combina a Series com serie2 ou escalar, usando func
compare(serie2[, align_axis, keep_shape, …]) Compara com serie2 exibindo differenças
copy([deep]) Faça uma cópia desse objeto, índices e valores
corr(serie2) Calcula a correlação com serie2, excluindo NaNs
count([level]) Retorna número de observações na Series, excluindo NaN/nulls
cov(serie2[, min_periods, ddof]) Calcula covariância da Series, excluindo NaN/nulls
cummax([axis, skipna]) Retorna máximo cumulativo
cummin([axis, skipna]) Retorna mínimo cumulativo
cumprod([axis, skipna]) Retorna o produto cumulativo
cumsum([axis, skipna]) Retorna a soma cumulativa
describe([percentiles, include, exclude, …]) Gera descrição estatística
div(serie2) Retorna divisão de ponto flutuante da series por serie2, elemento a elemento
divmod(serie2) Retorna divisão inteira e módulo da séries por serie2, elemento a elemento
dot(serie2) Calcula o produto interno entre a Series e serie2
drop([labels]) Retorna Series com labels removidos
drop_duplicates([keep, inplace]) Retorna Series após remoção de valores duplicados
dropna() Retorna Series após remoçaõ de valores faltantes
duplicated([keep]) Mostra os valores duplicados na Series
eq(serie2) Retorna Series de boolenos comparando elemento a elemento com serie2
equals(serie2) Boolenao: True se os dois objetos contém os mesmos elementos
ewm([com, span, halflife, alpha, …]) Calcula exponencial com peso
explode([ignore_index]) Transforma cada elemento de um objeto tipo lista em uma linha
fillna([value, method, axis, inplace, …]) Substitui valores NA/NaN usando método especificado
first(offset) Seleciona período inicial de uma série temporal usando offset.
first_valid_index() Retorna o índice do primeiro valor não NA/null
floordiv(serie2) Retorna divisão inteira da series por serie2, elemento a elemento
ge(serie2) Retorna serie booleana comparando se series é maior ou igual a serie2, elemento a elemento
get(key) Retorna item correspondente à key
groupby([by, axis, level, as_index, sort, …]) Agrupa a Series
gt(serie2[, level, fill_value, axis]) Retorna serie booleana comparando se series é maior que serie2, elemento a elemento
head([n]) Retorna os n primeiros valores
hist() Plota histograma da series usando matplotlib.
idxmax([axis, skipna]) Retorna o label do item de maior valor
idxmin([axis, skipna]) Retorna o label do item de menor valor
interpolate([method, axis, limit, inplace, …]) Preenche valores NaN usando metodo de interpolação
isin(valores) Booleano, se elementos da Series estão contidos em valores
isna() Booleano, se existem valores ausentes
isnull() Booleano, se existem valores nulos
item() Retorna primeiro elemento dos dados como escalar do Python
items() Iteração (lazy) sobre a tupla (index, value)
iteritems() Iteração (lazy) sobre a tupla (index, value)
keys() Alias de index
kurt([axis, skipna, level, numeric_only]) Retorna kurtosis imparcial
kurtosis([axis, skipna, level, numeric_only]) Retorna kurtosis imparcial
last(offset) Seleciona período final de uma série temporal usando offset
last_valid_index() Retorna o índice do último valor não NA/null
le(serie2) Retorna serie booleana comparando se series é menor ou igual a serie2, elemento a elemento
lt(serie2[, level, fill_value, axis]) Retorna serie booleana comparando se series é menor que serie2, elemento a elemento
mad([axis, skipna, level]) Retorna o desvio médio absoluto dos valores da series
mask(cond[, serie2, inplace, axis, level, …]) Substitui valores sob condição dada
max([axis, skipna, level, numeric_only]) Retorna o valor máximo
mean([axis, skipna, level, numeric_only]) Retorna a média dos valores
median([axis, skipna, level, numeric_only]) Retorna a mediana dos valores
memory_usage([index, deep]) Retorna a memória usada pela Series
min([axis, skipna, level, numeric_only]) Retorna o menor dos valores da series
mod(serie2[, level, fill_value, axis]) Retorna Modulo de series por serie2, elemento a elemento
mode([dropna]) Retorna a moda da Series
mul(serie2[, level, fill_value, axis]) Retorna a multiplicação de series por serie2, elemento a elemento
multiply(serie2[, level, fill_value, axis]) Retorna a multiplicação de series por serie2, elemento a elemento
ne(serie2[, level, fill_value, axis]) Retorna comparação booleana de series com serie2, elemento a elemento
nlargest([n, keep]) Retorna os n maiores elementos
notna() Booleano, se existem valores não faltantes ou nulos
notnull() Idem
nsmallest([n, keep]) Retorna os n menores elementos
nunique([dropna]) Retorna quantos elementos únicos existem na series
pad([axis, inplace, limit, downcast]) O mesmo que DataFrame.fillna() usando method=’ffill’
plot O mesmo que pandas.plotting._core.PlotAccessor
pop(item) Elimina valor da série com indice=item e retorna valor eliminado
pow(serie2) Retorna exponential de series por serie2, elemento a elemento
prod([axis, skipna, level, numeric_only, …]) Retorna o produto dos elemetos da series
product([axis, skipna, level, numeric_only, …]) Idem
quantile([q, interpolation]) Retorna valor na quantil dado
ravel([order]) Retorna os dados como um ndarray
rdiv(serie2[, level, fill_value, axis]) Executa a divisão de ponto flutuante de series por serie2, elemento a elemento
rdivmod(serie2) Retorna divisão inteira e módulo de series por serie2, elemento a elemento
reindex([index]) Ajusta a Series ao novo índice
reindex_like(serie2[, method, copy, limit, …]) Retorna um objeto com índices em acordo com serie2
rename([index, axis, copy, inplace, level, …]) Altera o nome ou labels dos índices
reorder_levels(order) Reajusta níveis de índices usando order
repeat(repeats[, axis]) Repete elementos da Series
replace([to_replace, value, inplace, limit, …]) Substitui valores em to_replace por value
reset_index([level, drop, name, inplace]) Gera nova Series reinicializando os índices
rfloordiv(serie2[, level, fill_value, axis]) Retorna divisão inteira de series por serie2, elemento a elemento
rmod(serie2[, level, fill_value, axis]) Retorna Modulo da divisão da series por serie2, elemento a elemento
rmul(serie2[, level, fill_value, axis]) Retorna multiplicação da series por serie2, elemento a elemento
round([n]) Arredonda valores da Series para n casas decimais.
rpow(serie2[, level, fill_value, axis]) Retorna a exponential de series por serie2, elemento a elemento
rsub(serie2[, level, fill_value, axis]) Retorna subtraction da series por serie2, elemento a elemento
rtruediv(serie2[, level, fill_value, axis]) Retorna divisão de ponto flutuante de series por serie2, elemento a elemento
sample([n, frac, replace, weights, …]) Retorna uma amostra randomizada de items da Series
searchsorted(value[, side, sorter]) Encontra índices de elementos de devem ser inseridos para manter a ordem
sem([axis, skipna, level, ddof, numeric_only]) Retorna erro padrão imparcial da média
skew([axis, skipna, level, numeric_only]) Retorna inclinação imparcial
sort_index([axis, level, ascending, …]) Reorganiza Series usando os labels dos índices
sort_values([axis, ascending, inplace, …]) Reorganiza Series usando seus valores
std([axis, skipna, level, ddof, numeric_only]) Retorna o desvio padrão da amostra
str Utiliza funções de string sobre elementos das series (se string). Ex. series.str.split(“-“)
sub(serie2) Retorna subtração de series por serie2, elemento a elemento
subtract(serie2) Idem
sum([axis, skipna, level, numeric_only, …]) Retorna soma dos valores da Series
tail([n]) Retorna os últimos n elemetnos
to_clipboard([excel, sep]) Copia o object para o clipboard do sistema
to_csv([path_or_buf, sep, na_rep, …]) Grava o object como arquivo csv (valores separados por vírgula)
to_dict([into]) Converte a Series para dicionário {label -> value}
to_excel(excel_writer[, sheet_name, na_rep, …]) Grava objeto como uma planilha do Excel
to_frame([name]) Converte Series em DataFrame
to_hdf(path_or_buf, key[, mode, complevel, …]) Grava dados da Series em arquivo HDF5 usando HDFStore
to_json([path_or_buf, orient, date_format, …]) Converte o objeto em uma string JSON
to_latex([buf, columns, col_space, header, …]) Renderiza objeto para LaTeX tabular, longtable, ou table/tabular aninhado.
to_lista() Retorna a lista dos valores
to_markdown([buf, mode, index, storage_options]) Escreve a Series em formato Markdown
to_numpy([dtype, copy, na_value]) Converte a series em NumPy ndarray
to_pickle(path[, compression, protocol, …]) Grava objeto serializado em arquivo Pickle
to_sql(name, con[, schema, if_exists, …]) Grava elementos em forma de um database SQL
to_string([buf, na_rep, float_format, …]) Constroi uma representação string da Series
tolist() Retorna uma lista dos valores
transform(func[, axis]) Executa func sobre elementos da serie
truediv(serie2) Retorna divisão de ponto flutuante de series por serie2, elemento a elemento
truncate([before, after, axis, copy]) Trunca a Series antes e após índices dados
unique() Retorna os valores da Series, sem repetições
update(serie2) Modifica a Series usando valores em serie2, sob índices especificados
value_counts([normalize, sort, ascending, …]) Retorna Series com a contagem de valores únicos
var([axis, skipna, level, ddof, numeric_only]) Retorna a variância imparcial dos valores da Series
view([dtype]) Cria uma nova “view” da Series
where(cond[, serie2, inplace, axis, level, …]) Substitui valores a condição cond é False
🔺Início do artigo

Bibliografia

  • Blair,Steve: Python Data Science, The Ultimate Handbook for Beginners on How to Explore NumPy for Numerical Data, Pandas for Data Analysis, IPython, Scikit-Learn and Tensorflow for Machine Learning and Business, edição do autor disponível na Amazon, 2019.
  • Harrison, Matt: Learning Pandas, Python Tools for Data Munging, Data Analysis, and Visualization,
    edição do autor, 2016.
  • McKinney, Wes: pandas: powerful Python data analysistoolkit, Release 1.2.1
    publicação do Pandas Development Team, revisado em 2021.
  • McKinney, Wes: Python for Data Analysis, Data Wrangling with Pandas, NumPy,and IPython
    O’Reilly Media, 2018.
  • Pandas: página oficial, acessada em janeiro de 2021.
  • Pandas User Guide, acessada em fevereiro de 2021.
  • Miller, Curtis: On Data Analysis with NumPy and pandas, Packt Publishing, Birmingham, 2018.

Deixe uma resposta

O seu endereço de e-mail não será publicado. Campos obrigatórios são marcados com *