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
é 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
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
eC++
.
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:
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 |
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.