Escolar Documentos
Profissional Documentos
Cultura Documentos
Em [76]: d
Fora[76]:
01
0 ah
1 bb
2 <NA>c
3 dd
dtype: string
Para concatenação com Série ou DataFrame, é possível alinhar os índices antes da concatenação definindo o
palavra-chave de junção.
Em [79]: s
Fora[79]:
0 a
1 b
2 c
3 d
dtype: string
Em [80]: você
Fora[80]:
1 b
3 d
0 a
c
2 dtype: string
Em [81]: s.str.cat(u)
Fora[81]:
0 ah
bb
1 CC
2 3 dd
dtype: string
1 bb
2 CC
3 dd
dtype: string
Aviso: Se a palavra-chave join não for passada, o método cat() retornará ao comportamento anterior
versão 0.23.0 (ou seja, sem alinhamento), mas um FutureWarning será gerado se algum dos índices envolvidos for diferente, uma vez que
este padrão será alterado para join='left' em uma versão futura.
As opções usuais estão disponíveis para junção (uma entre 'esquerda', 'externa', 'interna', 'direita'). Em particular, o alinhamento
também significa que os diferentes comprimentos não precisam mais coincidir.
Em [83]: v = pd.Series(["z", " a", "b", "d", "e"], índice=[-1, 0, 1, 3, 4], dtype= "corda")
Em [84]: s
Fora[84]:
0 a
1 b
2 c
3d
dtype: string
Em [85]: v
Fora[85]:
-1 z
0 a
1 b
3 d
4 e
dtype: string
2 3 dd
dtype: string
3 dd
4 -e
dtype: string
Em [89]: s
Fora[89]:
0 a
1 b
2 c
3 d
dtype: string
Em [90]: f
Fora[90]:
01
3 dd
2 <NA>c
1bb
0 ah
Vários itens semelhantes a array (especificamente: série, índice e variantes unidimensionais de np.ndarray) podem ser combinados
em um contêiner semelhante a uma lista (incluindo iteradores, visualizações de ditados, etc.).
Em [92]: s
Fora[92]:
0 a
1 b
2 c
3 d
dtype: string
Em [93]: você
Fora[93]:
1 b
3 d
0 a
2 c
dtype: string
Todos os elementos sem um índice (por exemplo, np.ndarray) dentro da lista passada devem corresponder em comprimento à série de chamada
(ou Índice), mas Série e Índice podem ter comprimento arbitrário (desde que o alinhamento não esteja desabilitado com join=None):
Em [95]: v
Fora[95]:
-1 z
0 a
b
1 d
34 e
dtype: string
Se estiver usando join='right' em uma lista de outras que contém índices diferentes, a união desses índices será usada
como base para a concatenação final:
Em [97]: u.loc[[3]]
Fora[97]:
3d
dtype: string
dtype: string
Você pode usar a notação [] para indexar diretamente por locais de posição. Se você indexar além do final da string, o resultado será
seja um NaN.
Em [100]: s = pd.Series(
.....: ["A", "B", "C", "Aaba", "Baca", np.nan, "CABA", "cachorro", "gato"], dtype=
ÿÿ"string"
..... :)
.....:
Em [101]: s.str[0]
Fora[101]:
0 A
1 B
2 C
3 A
4 B
5 <NA>
6 C
7 d
c
8 dtype: string
Em [102]: s.str[1]
Fora[102]:
0 <NA>
1 <NA>
2 <NA>
3 a
4 a
5 <NA>
6 A
7 ó
8 a
dtype: string
Aviso: Antes da versão 0.23, a expansão do argumento do método extract era padronizada como False. Quando
expand=False, expand retorna uma Série, Índice ou DataFrame, dependendo do assunto e da expressão regular
padrão. Quando expand=True, sempre retorna um DataFrame, que é mais consistente e menos confuso do que
a perspectiva de um usuário. expand=True é o padrão desde a versão 0.23.0.
O método extract aceita uma expressão regular com pelo menos um grupo de captura.
Extrair uma expressão regular com mais de um grupo retorna um DataFrame com uma coluna por grupo.
Em [103]: pd.Series(
.....: ["a1", "b2", "c3"],
.....: dtype="string",
.....: .str.extract(r"([ab])(\d)", expandir=Falso)
.....:
Fora[103]:
0 1
0 a 1
1b2
2 <NA> <NA>
Elementos que não correspondem retornam uma linha preenchida com NaN. Assim, uma série de strings confusas pode ser “convertida” em uma
Série ou DataFrame com indexação semelhante de strings limpas ou mais úteis, sem a necessidade de get() para acessar tuplas
ou re.match objetos. O dtype do resultado é sempre objeto, mesmo que nenhuma correspondência seja encontrada e o resultado contenha apenas
NaN.
Em [105]: pd.Series(
.....: ["a1", "b2", "3"],
.....: dtype="string",
.....: .str.extract(r"([ab])?(\d)", expandir=Falso)
.....:
Fora[105]:
01
0 um 1
1 b2
2 <NA> 3
também pode ser usado. Observe que quaisquer nomes de grupos de captura na expressão regular serão usados para nomes de colunas; de outra forma
números de grupo de captura serão usados.
Extrair uma expressão regular com um grupo retorna um DataFrame com uma coluna se expand=True.
Chamar um índice com uma regex com exatamente um grupo de captura retorna um DataFrame com uma coluna se
expandir = Verdadeiro.
Em [109]: s
Fora[109]:
A11 a1
B22 b2
Capítulo 33 c3
dtype: string
Chamar um índice com uma regex com mais de um grupo de captura retorna um DataFrame se expand=True.
A tabela abaixo resume o comportamento de extract(expand=False) (assunto de entrada na primeira coluna, número de
grupos em regex na primeira linha)
Em [114]: s
Fora[114]:
A1a2
B b1
C c1
dtype: string
o método extractall retorna todas as correspondências. O resultado do extractall é sempre um DataFrame com MultiIndex
em suas fileiras. O último nível do MultiIndex é denominado match e indica a ordem do assunto.
Em [117]: s.str.extractall(dois_grupos)
Fora[117]:
dígito da letra
corresponder
Um 0 a 1
1 a 2
B0 b 1
C0 c 1
Em [119]: s
Fora[119]:
0 a3
1 b3
2 c2
dtype: string
Em [121]: extract_result
Fora[121]:
dígito da letra
0 a 3
1 b 3
(continua na próxima página)
2 c 2
Em [123]: extractall_result
Fora[123]:
dígito da letra
corresponder
00 a 3
10 b 3
20 c 2
O índice também suporta .str.extractall. Ele retorna um DataFrame que tem o mesmo resultado que Series.str.
extractall com um índice padrão (começa em 0).
00 a 1
1 a 2
10 b 1
20 c 1
00 a 1
a 2
11 b 1
020 c 1
Em [128]: pd.Series(
.....: ["1", "2", "3a", "3b", "03c", "4dx"],
.....: dtype="string",
.....: .str.contains(padrão)
.....:
(continua na próxima página)
Fora[128]:
0 Falso
1 Falso
2 Verdadeiro
3 Verdadeiro
4 Verdadeiro
5 Verdadeiro
tipo d: booleano
Em [129]: pd.Series(
.....: ["1", "2", "3a", "3b", "03c", "4dx"],
.....: dtype="string",
.....: .str.match(padrão)
.....:
Fora[129]:
0 Falso
1 Falso
2 Verdadeiro
3 Verdadeiro
4 Falso
5 Verdadeiro
tipo d: booleano
Em [130]: pd.Series(
.....: ["1", "2", "3a", "3b", "03c", "4dx"],
.....: dtype="string",
.....: .str.fullmatch(padrão)
.....:
Fora[130]:
0 Falso
1 Falso
2 Verdadeiro
3 Verdadeiro
4 Falso
5 Falso
tipo d: booleano
Nota: A distinção entre match, fullmatch e contains é rigorosa: fullmatch testa se o conteúdo inteiro
string corresponde à expressão regular; match testa se há uma correspondência da expressão regular que começa em
o primeiro caractere da string; e contém testes se há uma correspondência da expressão regular em qualquer posição
dentro da string.
As funções correspondentes no pacote re para esses três modos de correspondência são re.fullmatch, re.match e re.search,
respectivamente.
Métodos como match, fullmatch, contains, começa com e termina com recebem um argumento extra que falta
os valores podem ser considerados verdadeiros ou falsos:
Em [131]: s4 = pd.Series(
.....: ["A", "B", "C", "Aaba", "Baca", np.nan, "CABA", "cachorro", "gato"], dtype=
ÿÿ"string"
..... :)
.....:
Falso
Falso
Verdadeiro
1 2 3 4 Falso
5 Falso
6 Verdadeiro
7 Falso
8 Falso
tipo d: booleano
Você pode extrair variáveis fictícias de colunas de string. Por exemplo, se eles estiverem separados por um '|':
Em [134]: s.str.get_dummies(sep="|")
Fora[134]:
abc
0100
1110
2000
3101
Em [136]: idx.str.get_dummies(sep="|")
Fora[136]:
MultiÍndice([(1, 0, 0),
(1, 1, 0),
(0, 0, 0),
(1, 0, 1)],
nomes=['a', 'b', 'c'])
Método Descrição
cat() Concatenar strings
split() Dividir strings no delimitador
rsplit() get() Dividir strings no delimitador trabalhando a partir do final da string
join() Indexar em cada elemento (recuperar o i-ésimo elemento)
Junte strings em cada elemento da Série com separador passado
get_dummies() Dividir strings no delimitador retornando DataFrame de variáveis fictícias
contém() Retorna um array booleano se cada string contiver padrão/regex
replace() Substitua as ocorrências de padrão/regex/string por alguma outra string ou pelo valor de retorno de um
chamável dada a ocorrência
removerprefixo() Remova o prefixo da string, ou seja, remova apenas se a string começar com prefixo.
removesufixo() Remova o sufixo da string, ou seja, remova apenas se a string terminar com sufixo.
repita() Valores duplicados (s.str.repeat(3) equivalente a x pad() * 3)
Adicione espaços em branco à esquerda, à direita ou em ambos os lados das strings
Nota: A escolha de usar NaN internamente para denotar dados ausentes foi em grande parte por razões de simplicidade e desempenho.
A partir do pandas 1.0, alguns tipos de dados opcionais começam a experimentar um escalar NA nativo usando um método baseado em máscara
abordagem. Veja aqui para mais.
Como os dados vêm em vários formatos e formatos, o pandas pretende ser flexível no que diz respeito ao tratamento de dados ausentes. Enquanto
NaN é o marcador de valor ausente padrão por razões de velocidade computacional e conveniência, precisamos ser capazes de
detecte facilmente esse valor com dados de diferentes tipos: ponto flutuante, inteiro, booleano e objeto geral. Em muitos casos,
no entanto, o Python None surgirá e desejamos também considerar isso “ausente” ou “não disponível” ou “NA”.
Nota: Se quiser considerar inf e -inf como “NA” nos cálculos, você pode definir pandas.options.mode.
use_inf_as_na = Verdadeiro.
Em [1]: df = pd.DataFrame(
...: np.random.randn(5, 3),
...: índice=["a", "c", "e", "f", "h"],
...: colunas=["um", "dois", "três"],
... :)
...:
Em [4]: df
Fora[4]:
um dois três quatro cinco
a 0,469112 -0,282863 -1,509059 barra Verdadeiro
c -1,135632 1,212112 -0,173215 barra Falso
e 0,119209 -1,044236 -0,861849 barra Verdadeiro
f -2,104569 -0,494929 1,071804 barra Falso
(continua na próxima página)
Em [5]: df2 = df.reindex(["a", "b", "c", "d", "e", "f", "g", "h"])
Em [6]: df2
Fora[6]:
um dois três quatro cinco
a 0,469112 -0,282863 -1,509059 barra Verdadeiro
NaN NaN NaN NaN NaN
bc -1,135632 1,212112 -0,173215 barra Falso
NaN NaN NaN NaN NaN
de 0,119209 -1,044236 -0,861849 barra Verdadeiro
f -2,104569 -0,494929 1,071804 barra Falso
NaN NaN NaN NaN NaN
gh 0,721555 -0,706771 -1,039575 barra Verdadeiro
Para facilitar a detecção de valores ausentes (e em diferentes tipos de array), o pandas fornece isna() e notna()
funções, que também são métodos em objetos Series e DataFrame:
Em [7]: df2["um"]
Fora[7]:
a 0,469112
b NaN
c-1,135632
d NaN
e 0,119209
f-2.104569
NaN
gh 0,721555
Nome: um, dtype: float64
Em [8]: pd.isna(df2["um"])
Fora[8]:
a Falso
b Verdadeiro
c Falso
d Verdadeiro
e Falso
f Falso
Verdadeiro
ah Falso
Nome: um, dtype: bool
Em [9]: df2["quatro"].notna()
Fora[9]:
a Verdadeiro
b Falso
c Verdadeiro
d Falso
e Verdadeiro
f Verdadeiro
g Falso
(continua na próxima página)
Em [10]: df2.isna()
Fora[10]:
um dois três quatro cinco
um Falso Falso Falso Falso Falso
b Verdadeiro Verdadeiro Verdadeiro Verdadeiro
c Falso Falso Falso Falso Falso
d Verdadeiro Verdadeiro Verdadeiro Verdadeiro
e Falso Falso Falso Falso Falso
f Falso Falso Falso Falso Falso
g Verdadeiro Verdadeiro Verdadeiro Verdadeiro
h Falso Falso Falso Falso Falso
Aviso: é preciso estar ciente de que em Python (e NumPy), os nan's não são iguais, mas os None's sim.
Observe que o pandas/NumPy usa o fato de que np.nan! = np.nan e trata None como np.nan.
Portanto, em comparação com o acima, uma comparação de igualdade escalar versus None/np.nan não fornece informações úteis.
Como NaN é um float, uma coluna de inteiros com pelo menos um valor ausente é convertida em dtype de ponto flutuante (consulte Suporte
para inteiro NA para mais). pandas fornece um array inteiro anulável, que pode ser usado solicitando explicitamente o dtype:
Alternativamente, a string alias dtype='Int64' (observe o "I" maiúsculo) pode ser usada.
Data e hora
Para tipos datetime64[ns], NaT representa valores ausentes. Este é um valor sentinela pseudo-nativo que pode ser representado
por NumPy em um dtype singular (datetime64[ns]). objetos pandas fornecem compatibilidade entre NaT e NaN.
Em [17]: df2
Fora[17]:
um dois três quatro cinco carimbo de data/hora
a 0,469112 -0,282863 -1,509059 barra Verdadeiro 01/01/2012
c -1,135632 1,212112 -0,173215 barra Falso 01/01/2012
e 0,119209 -1,044236 -0,861849 barra Verdadeiro 01/01/2012
f -2,104569 -0,494929 1,071804 barra Falso 01/01/2012
h 0,721555 -0,706771 -1,039575 barra Verdadeiro 01/01/2012
Em [19]: df2
Fora[19]:
um dois três quatro cinco carimbo de data/hora
a NaN -0,282863 -1,509059 bar Verdadeiro NaT
c NaN 1,212112 -0,173215 bar Falso NaT
e 0,119209 -1,044236 -0,861849 barra Verdadeiro 01/01/2012
f -2,104569 -0,494929 1,071804 barra Falso 01/01/2012
h NaN -0,706771 -1,039575 barra Verdadeiro NaT
Em [20]: df2.dtypes.value_counts()
Fora[20]:
float64 3
objeto 1
bool 1
datetime64[ns] dtype: 1
int64
Você pode inserir valores ausentes simplesmente atribuindo aos contêineres. O valor faltante real usado será escolhido com base
no tipo d.
Por exemplo, contêineres numéricos sempre usarão NaN, independentemente do tipo de valor ausente escolhido:
Em [23]: s
Fora[23]:
0 NaN
1 2,0
2 3,0
tipo d: float64
Em [27]: s
Fora[27]:
0 Nenhum
1 NaN
2 c
dtype: objeto
Em [28]: uma
Fora[28]:
um dois
a NaN-0,282863
c NaN 1,212112
e 0,119209 -1,044236
f -2,104569 -0,494929
h -2,104569 -0,706771
Em [29]: b
Fora[29]:
um dois três
a NaN -0,282863 -1,509059
c NaN 1,212112 -0,173215
e 0,119209 -1,044236 -0,861849
f -2,104569 -0,494929 1,071804
h NaN -0,706771 -1,039575
Em [30]: a + b
Fora[30]:
um três dois
a NaN NaN-0,565727
c NaN NaN 2,424224
(continua na próxima página)
As estatísticas descritivas e métodos computacionais discutidos na visão geral da estrutura de dados (e listados aqui e aqui)
são todos gravados para compensar dados ausentes. Por exemplo:
• Métodos cumulativos como cumsum() e cumprod() ignoram os valores NA por padrão, mas os preservam no
matrizes resultantes. Para substituir esse comportamento e incluir valores NA, use skipna=False.
Em [31]: df
Fora[31]:
um dois três
a NaN -0,282863 -1,509059
c NaN 1,212112 -0,173215
e 0,119209 -1,044236 -0,861849
f -2,104569 -0,494929 1,071804
h NaN -0,706771 -1,039575
Em [32]: df["um"].sum()
Saída[32]: -1,9853605075978744
Em [33]: df.mean(1)
Fora[33]:
-0,895961
c 0,519449
e-0,595625
f -0,509232
h-0,873173
tipo d: float64
Em [34]: df.cumsum()
Fora[34]:
um dois três
a NaN -0,282863 -1,509059
c NaN 0,929249 -1,682273
e 0,119209 -0,114987 -2,544122
f -1,985361 -0,609917 -1,472318
h NaN -1,316688 -2,511893
Em [35]: df.cumsum(skipna=False)
Fora[35]:
um dois três
aNaN -0,282863 -1,509059
cNaN 0,929249 -1,682273
eNaN -0,114987 -2,544122
fNaN -0,609917 -1,472318
hNaN -1,316688 -2,511893
Aviso: Este comportamento agora é padrão a partir da v0.22.0 e é consistente com o padrão em numpy; anteriormente, soma/produção
de séries/DataFrames totalmente NA ou vazias retornaria NaN. Consulte novidades da v0.22.0 para obter mais informações.
Em [36]: pd.Series([np.nan]).sum()
Fora[36]: 0,0
Em [38]: pd.Series([np.nan]).prod()
Fora[38]: 1,0
Os grupos NA em GroupBy são automaticamente excluídos. Este comportamento é consistente com R, por exemplo:
Em [40]: df
Fora[40]:
um dois três
a NaN -0,282863 -1,509059 NaN
c 1,212112 -0,173215 e 0,119209
-1,044236 -0,861849 f -2,104569 -0,494929
1,071804 NaN -0,706771 -1,039575
h
Em [41]: df.groupby("um").mean()
Fora[41]:
dois três
um
-2,104569 -0,494929 1,071804
0,119209 -1,044236 -0,861849
Os objetos pandas são equipados com vários métodos de manipulação de dados para lidar com dados ausentes.
fillna() pode “preencher” valores NA com dados não-NA de duas maneiras, que ilustramos:
Em [42]: df2
Fora[42]:
um dois três quatro cinco carimbo de data/hora
a NaN -0,282863 -1,509059 bar Verdadeiro NaT
c NaN 1,212112 -0,173215 barra Falso NaT
e 0,119209 -1,044236 -0,861849 barra Verdadeiro 01/01/2012
f -2,104569 -0,494929 1,071804 barra Falso 01/01/2012
h NaN -0,706771 -1,039575 barra Verdadeiro NaT
Em [43]: df2.fillna(0)
Fora[43]:
um dois três quatro cinco carimbo de data/hora
a 0,000000 -0,282863 -1,509059 barra Verdadeiro 0
c 0,000000 1,212112 -0,173215 barra Falso 0
e 0,119209 -1,044236 -0,861849 barra Verdadeiro 01/01/2012 00:00:00
f -2,104569 -0,494929 1,071804 barra Falso 01/01/2012 00:00:00
h 0,000000 -0,706771 -1,039575 barra Verdadeiro 0
Em [44]: df2["um"].fillna("ausente")
Fora[44]:
a ausente
c ausente
e 0,119209
f-2.104569
estou faltando
Nome: um, dtype: objeto
Usando os mesmos argumentos de preenchimento da reindexação, podemos propagar valores não-NA para frente ou para trás:
Em [45]: df
Fora[45]:
um dois três
a NaN -0,282863 -1,509059
c NaN 1,212112 -0,173215
e 0,119209 -1,044236 -0,861849
f -2,104569 -0,494929 1,071804
hNaN -0,706771 -1,039575
Em [46]: df.fillna(método="pad")
Fora[46]:
um dois três
a NaN -0,282863 -1,509059
(continua na próxima página)
Se quisermos apenas que lacunas consecutivas sejam preenchidas até um certo número de pontos de dados, podemos usar a palavra-chave limit:
Em [47]: df
Fora[47]:
um dois três
aNaN -0,282863 -1,509059
cNaN 1,212112 -0,173215
e NaN NaN NaN
fNaN NaN NaN
hNaN -0,706771 -1,039575
Método Ação
almofada / Preencha os valores adiante
Com dados de série temporal, o uso de pad/ffill é extremamente comum para que o “último valor conhecido” esteja sempre disponível
apontar.
Você também pode preencher usando um ditado ou série que seja alinhável. Os rótulos do dict ou índice da Série devem corresponder ao
colunas do quadro que você deseja preencher. O caso de uso disso é preencher um DataFrame com a média dessa coluna.
Em [53]: dff
(continua na próxima página)
Fora[53]:
A B C
0 0,271860 -0,424972 0,567020
10,276232 -1,087401 -0,673690
2 0,113648 -1,478427 0,524988
3 NaN 0,577046 -1,715002
4 NaN NaN -1,157892
5-1,344312 NaN NaN
6 -0,109050 1,643563 NaN
7 0,357021 -0,674600 NaN
8 -0,968914 -1,294524 0,413738
9 0,276662 -0,472035 -0,013960
Em [54]: dff.fillna(dff.mean())
Fora[54]:
A B C
0 0,271860 -0,424972 0,567020
10,276232 -1,087401 -0,673690
2 0,113648 -1,478427 0,524988
3 -0,140857 0,577046 -1,715002
4 -0,140857 -0,401419 -1,157892
5 -1,344312 -0,401419 -0,293543
6 -0,109050 1,643563 -0,293543
7 0,357021 -0,674600 -0,293543
8 -0,968914 -1,294524 0,413738
9 0,276662 -0,472035 -0,013960
Em [55]: dff.fillna(dff.mean()["B":"C"])
Fora[55]:
A B C
0 0,271860 -0,424972 0,567020
10,276232 -1,087401 -0,673690
2 0,113648 -1,478427 0,524988
3 NaN 0,577046 -1,715002
4 NaN -0,401419 -1,157892
5 -1,344312 -0,401419 -0,293543
6 -0,109050 1,643563 -0,293543
7 0,357021 -0,674600 -0,293543
8 -0,968914 -1,294524 0,413738
9 0,276662 -0,472035 -0,013960
O mesmo resultado acima, mas está alinhando o valor de 'preenchimento' que é uma Série neste caso.
Você pode simplesmente excluir rótulos de um conjunto de dados que se referem a dados ausentes. Para fazer isso, use dropna():
Em [57]: df
Fora[57]:
um dois três
aNaN -0,282863 -1,509059
cNaN 1,212112 -0,173215
eNaN 0,000000 0,000000
f NaN 0,000000 0,000000 h NaN -0,706771
-1,039575
Em [58]: df.dropna(eixo=0)
Out[58]:
Colunas vazias do
DataFrame: [um, dois, três]
Índice: []
Em [59]: df.dropna(eixo=1)
Fora[59]:
dois três
a -0,282863 -1,509059
c 1,212112 -0,173215
e 0,000000 0,000000
f 0,000000 0,000000 h -0,706771
-1,039575
Em [60]: df["um"].dropna()
Out[60]: Series([], Nome: um, dtype: float64)
Um dropna() equivalente está disponível para séries. DataFrame.dropna tem consideravelmente mais opções que Series.dropna,
que podem ser examinadas na API.
2.10.9 Interpolação
Os objetos Series e DataFrame possuem interpolate() que, por padrão, executa interpolação linear em pontos de dados ausentes.
Em [61]: ts
Saída[61]:
31/01/2000 0,469112
29/02/2000 NaN
31/03/2000 NaN
28/04/2000 NaN
(continua na próxima página)
31/05/2000 NaN
...
31-12-2007 -6.950267
31/01/2008 -7.904475
29/02/2008 -6.441779
31/03/2008 -8.184940
30/04/2008 -9.011531
Freq: BM, Comprimento: 100, tipo d: float64
Em [62]: ts.count()
Fora[62]: 66
Em [63]: ts.plot()
Saída[63]: <AxesSubplot:>
Em [64]: ts.interpolate()
Fora[64]:
31/01/2000 0,469112
29/02/2000 0,434469
31/03/2000 0,399826
28/04/2000 0,365184
31/05/2000 0,330541
(continua na próxima página)
...
31-12-2007 -6.950267
31/01/2008 -7.904475
29/02/2008 -6.441779
31/03/2008 -8.184940
30/04/2008 -9.011531
Freq: BM, Comprimento: 100, tipo d: float64
Em [65]: ts.interpolate().count()
Fora[65]: 100
Em [66]: ts.interpolate().plot()
Saída[66]: <AxesSubplot:>
A interpolação com reconhecimento de índice está disponível por meio da palavra-chave method:
Em [67]: ts2
Saída[67]:
31/01/2000 0,469112
29/02/2000 NaN
31/07/2002 -5,785037
31/01/2005 NaN
(continua na próxima página)
30/04/2008 -9.011531
tipo d: float64
Em [68]: ts2.interpolate()
Fora[68]:
31/01/2000 0,469112
29/02/2000 -2,657962
31/07/2002 -5,785037
31-01-2005 -7.398284
30/04/2008 -9.011531
tipo d: float64
Em [69]: ts2.interpolate(method="time")
Fora[69]:
31/01/2000 0,469112
29/02/2000 0,270241
31/07/2002 -5,785037
31/01/2005 -7.190866
30/04/2008 -9.011531
tipo d: float64
Em [70]: ser
Fora[70]:
0,0 0,0
1,0 NaN
10,0 10,0
tipo d: float64
Em [71]: ser.interpolate()
Fora[71]:
0,0 0,0
1,0 5,0
10,0 10,0
tipo d: float64
Em [72]: ser.interpolate(method="values")
Fora[72]:
0,0 0,0
1,0 1,0
10,0 10,0
tipo d: float64
Em [73]: df = pd.DataFrame(
....: {
....: "A": [1, 2,1, np.nan, 4,7, 5,6, 6,8],
....: "B": [0,25, np.nan, np.nan, 4, 12,2, 14,4],
....: }
....: )
(continua na próxima página)
....:
Em [74]: df
Fora[74]:
A B
0 1,0 0,25
1 2.1 NaN
2NaN NaN
3 4,7 4,00
4 5,6 12,20
5 6,8 14,40
Em [75]: df.interpolate()
Fora[75]:
A B
0 1,0 0,25 1 2,1
1,50 2 3,4 2,75 3
4,7 4,00 4 5,6 12,20
5 6,8 14,40
O argumento do método dá acesso a métodos de interpolação mais sofisticados. Se você tiver o scipy instalado, poderá passar o nome
de uma rotina de interpolação 1-d para o método. Você vai querer consultar a documentação completa de interpolação scipy e o guia
de referência para obter detalhes. O método de interpolação apropriado dependerá do tipo de dados com os quais você está trabalhando.
• Se você estiver lidando com uma série temporal que está crescendo a uma taxa crescente, method='quadratic' pode ser apropriado.
privado.
• Se você tiver valores aproximados de uma função de distribuição cumulativa, então method='pchip' deverá funcionar bem.
• Para preencher valores faltantes com o objetivo de plotagem suave, considere method='akima'.
Em [76]: df.interpolate(method="barycentric")
Fora[76]:
A B
0 1,00 0,250 1 2,10
-7,660 2 3,53 -4,515
3 4,70 4,000 4 5,60
12,200 5 6,80 14,400
Em [77]: df.interpolate(method="pchip")
Fora[77]:
A B
0 1,00000 0,250000 1 2,10000
0,672808
2 3,43454 1,928950
3 4,70000 4,000000
(continua na próxima página)
Em [78]: df.interpolate(method="akima")
Fora[78]:
A B
0 1,000000 0,250000
12,100000 -0,873316
2 3,406667 0,320034
3 4,700000 4,000000
4 5,600000 12,200000 5 6,800000
14,400000
Ao interpolar através de uma aproximação polinomial ou spline, você também deve especificar o grau ou a ordem da aproximação:
Em [81]: np.random.seed(2)
Em [83]: ausente = np.array([4, 13, 14, 15, 16, 17, 18, 20, 29])
Em [87]: df.plot()
Saída[87]: <AxesSubplot:>
Outro caso de uso é a interpolação em novos valores. Suponha que você tenha 100 observações de alguma distribuição. E vamos
suponha que você esteja particularmente interessado no que está acontecendo no meio. Você pode misturar a reindexação dos pandas e
métodos de interpolação para interpolar nos novos valores.
# interpolar em new_index
Em [89]: new_index = ser.index.union(pd.Index([49,25, 49,5, 49,75, 50,25, 50,5, 50,75]))
Em [91]: interp_s[49:51]
Fora[91]:
49,00 0,471410
49,25 0,476841
49,50 0,481780
49,75 0,485998
50,00 0,489266
50,25 0,491814
50,50 0,493995
50,75 0,495763
51,00 0,497074
tipo d: float64
Limites de interpolação
Como outros métodos de preenchimento do pandas, interpolate() aceita um argumento de palavra-chave limit. Use este argumento para limitar o
número de valores NaN consecutivos preenchidos desde a última observação válida:
Em [92]: ser = pd.Series([np.nan, np.nan, 5, np.nan, np.nan, np.nan, 13, np.nan, np.nan])
Em [93]: ser
Fora[93]:
0 NaN
1 NaN
2 5,0
3 NaN
4 NaN
5 NaN
6 13,0
7 NaN
8 NaN
tipo d: float64
Por padrão, os valores NaN são preenchidos na direção direta. Use o parâmetro limit_direction para preencher para trás ou de
ambas direcoes.
0 NaN
1 5,0
2 5,0
3 NaN
4 NaN
5 11,0
6 13,0
7 NaN
8 NaN
tipo d: float64
Por padrão, os valores NaN são preenchidos quer estejam dentro (cercados por) valores válidos existentes ou fora dos valores válidos existentes.
valores. O parâmetro limit_area restringe o preenchimento a valores internos ou externos.
7 NaN
8 NaN
tipo d: float64
replace() em Series e replace() em DataFrame fornecem uma maneira eficiente, porém flexível, de realizar tais substituições.
Para uma série, você pode substituir um único valor ou uma lista de valores por outro valor:
Em [103]: ser.replace(0, 5)
Fora[103]:
0 5,0
1 1,0
2 2,0
3 3,0
4 4,0
tipo d: float64
Você pode substituir uma lista de valores por uma lista de outros valores:
227
338
4 4 9
Em vez de substituir por valores especificados, você pode tratar todos os valores fornecidos como ausentes e interpolar sobre eles:
Nota: Strings Python prefixadas com o caractere r, como r'hello world', são chamadas de strings “brutas”. Eles têm
semântica diferente em relação às barras invertidas das strings sem esse prefixo. Barras invertidas em strings brutas serão interpretadas
como uma barra invertida com escape, por exemplo, r'\' == '\\'. Você deve ler sobre eles se isso não estiver claro.
Em [109]: d = {"a": list(range(4)), "b": list("ab.."), "c": ["a", "b", np.nan, "d"]}
Em [110]: df = pd.DataFrame(d)
Agora faça isso com uma expressão regular que remove os espaços em branco circundantes (regex -> regex):
Igual ao exemplo anterior, mas use uma expressão regular para pesquisar (dict of regex -> dict):
Você pode passar dicionários aninhados de expressões regulares que usam regex=True:
Você também pode usar o grupo de correspondência de expressão regular ao substituir (dict of regex -> dict of regex), isso funciona para
listas também.
Você pode passar uma lista de expressões regulares, das quais aquelas que corresponderem serão substituídas por um escalar (lista de regex ->
regex).
ab c
0 0 NaN NaN
1 1 NaN NaN
2 2 NaN NaN
3 3 NaN d
Todos os exemplos de expressões regulares também podem ser passados com o argumento to_replace como argumento regex. Em
neste caso, o argumento value deve ser passado explicitamente por nome ou regex deve ser um dicionário aninhado. O anterior
exemplo, neste caso, seria então:
Isso pode ser conveniente se você não quiser passar regex=True toda vez que quiser usar uma expressão regular.
Nota: Em qualquer lugar nos exemplos de substituição acima onde você vê uma expressão regular, uma expressão regular compilada é
válido também.
Fora[126]:
0 1
0 -1,021415
10,432396 -0,323580
2 0,423825 0,799180
3 1,262614 0,751965
4 NaN NaN
5 NaN NaN
6 -0,498174 -1,060799
7 0,591667 -0,183257
8 1,019855 -1,482465
9 NaN NaN
Em [127]: df[1].dtype
Fora[127]: dtype('float64')
Embora o pandas suporte o armazenamento de matrizes do tipo inteiro e booleano, esses tipos não são capazes de armazenar dados ausentes.
Até que possamos passar a usar um tipo NA nativo no NumPy, estabelecemos algumas “regras de transmissão”. Quando uma reindexação
operação introduz dados faltantes, a Série será lançada de acordo com as regras introduzidas na tabela abaixo.
inteiro flutuador
booleano objeto
objeto sem elenco
Por exemplo:
Em [130]: s > 0
Fora[130]:
0 Verdadeiro
2 Verdadeiro
4 Verdadeiro
6 Verdadeiro
7 Verdadeiro
tipo d: bool
Em [133]: crítica
Fora[133]:
0 Verdadeiro
1 NaN
2 Verdadeiro
3 NaN
4 Verdadeiro
5 NaN
6 Verdadeiro
7 Verdadeiro
dtype: objeto
Em [134]: crit.dtype
Fora[134]: dtype('O')
Normalmente, o NumPy reclamará se você tentar usar um array de objetos (mesmo que contenha valores booleanos) em vez de um
array booleano para obter ou definir valores de um ndarray (por exemplo, selecionar valores com base em alguns critérios). Se um vetor booleano
contém NAs, uma exceção será gerada:
Em [136]: reindexado[crit]
-------------------------------------------------- -------------------------
ValueError: Não é possível mascarar com array não booleano contendo valores NA/NaN
Em [137]: reindexado[crit.fillna(False)]
Fora[137]:
0 0,126504
20,696198
4 0,697416
(continua na próxima página)
6 0,601516
7 0,003659
tipo d: float64
Em [138]: reindexado[crit.fillna(True)]
Fora[138]:
0 0,126504
1 0,000000
2 0,696198
3 0,000000
4 0,697416
5 0,000000
6 0,601516
7 0,003659
tipo d: float64
pandas fornece um tipo inteiro anulável, mas você deve solicitá-lo explicitamente ao criar a série ou coluna. Perceber
que usamos um “I” maiúsculo em dtype="Int64".
Em [140]: s
Fora[140]:
0 0
1 1
2 <NA>
3 3
4 4
tipo de d: Int64
Aviso: Experimental: o comportamento do pd.NA ainda pode mudar sem aviso prévio.
A partir do pandas 1.0, um valor experimental pd.NA (singleton) está disponível para representar valores escalares ausentes. No
neste momento, ele é usado nos tipos de dados inteiro anulável, booleano e string dedicado como indicador de valor ausente.
O objetivo do pd.NA é fornecer um indicador “ausente” que possa ser usado consistentemente em todos os tipos de dados (em vez de np.nan,
Nenhum ou pd.NaT dependendo do tipo de dados).
Por exemplo, ao ter valores ausentes em uma série com o dtype inteiro anulável, ele usará pd.NA:
Em [142]: s
Fora[142]:
01
Em [143]: s[2]
Fora[143]: <NA>
Atualmente, o pandas ainda não usa esses tipos de dados por padrão (ao criar um DataFrame ou Série, ou ao ler dados), então você precisa
especificar o dtype explicitamente. Uma maneira fácil de converter para esses tipos é explicada aqui.
Em geral, os valores faltantes se propagam em operações envolvendo pd.NA. Quando um dos operandos é desconhecido, o resultado da
operação também é desconhecido.
Existem alguns casos especiais em que o resultado é conhecido, mesmo quando um dos operandos é NA.
Nas operações de igualdade e comparação, pd.NA também se propaga. Isso se desvia do comportamento de np.nan, onde comparações
com np.nan sempre retornam False.
Para verificar se um valor é igual a pd.NA, a função isna() pode ser usada:
Em [152]: pd.isna(pd.NA)
Fora[152]: Verdadeiro
Uma exceção a esta regra básica de propagação são as reduções (como a média ou o mínimo), onde o padrão do pandas é pular valores
ausentes. Veja acima para mais.
Operações lógicas
Para operações lógicas, pd.NA segue as regras da lógica de três valores (ou lógica Kleene, semelhante a R, SQL e Julia). Essa lógica
significa propagar valores ausentes apenas quando for logicamente necessário.
Por exemplo, para a operação lógica “ou” (|), se um dos operandos for Verdadeiro, já sabemos que o resultado será Verdadeiro,
independentemente do outro valor (portanto, independentemente do valor faltante seria Verdadeiro ou Falso). Neste caso, pd.NA não se
propaga:
Por outro lado, se um dos operandos for False, o resultado depende do valor do outro operando. Portanto, neste caso pd.NA propaga:
O comportamento da operação lógica “e” (&) pode ser derivado usando lógica semelhante (onde agora pd.NA não será propagado se um
dos operandos já for Falso):
NA em um contexto booleano
Como o valor real de um NA é desconhecido, é ambíguo converter NA em um valor booleano. Os seguintes aumentos
um erro:
Em [165]: bool(pd.NA)
-------------------------------------------------- -------------------------
Isso também significa que pd.NA não pode ser usado em um contexto onde é avaliado como booleano, como if condição: ... onde
condição pode potencialmente ser pd.NA. Nesses casos, isna() pode ser usado para verificar pd.NA ou a condição pd.NA pode
ser evitada, por exemplo, preenchendo os valores ausentes antecipadamente.
Uma situação semelhante ocorre ao usar objetos Series ou DataFrame em instruções if, consulte Usando instruções if/ truth com
pandas.
NumPy ufuncs
pandas.NA implementa o protocolo __array_ufunc__ do NumPy. A maioria dos ufuncs trabalha com NA e geralmente retorna NA:
Em [166]: np.log(pd.NA)
Fora[166]: <NA>
Em [167]: np.add(pd.NA, 1)
Fora[167]: <NA>
Aviso: Atualmente, ufuncs envolvendo um ndarray e NA retornarão um object-dtype preenchido com valores NA.
O tipo de retorno aqui pode mudar para retornar um tipo de array diferente no futuro.
Consulte Interoperabilidade do DataFrame com funções NumPy para obter mais informações sobre ufuncs.
Conversão
Se você tiver um DataFrame ou Série usando tipos tradicionais que possuem dados ausentes representados usando np.nan, existem
métodos de conveniência convert_dtypes() em Series e convert_dtypes() em DataFrame que podem converter dados em
use os dtypes mais recentes para números inteiros, strings e booleanos listados aqui. Isso é especialmente útil depois de ler conjuntos de dados
ao permitir que leitores como read_csv() e read_excel() inferam dtypes padrão.
Neste exemplo, enquanto os dtypes de todas as colunas são alterados, mostramos os resultados das primeiras 10 colunas.
Em [171]: bb[bb.columns[:10]].dtypes
Fora[171]:
período objeto
do ano int64
do jogador int64
equipe objeto
lg objeto
int64
g ab int64
R int64
h int64
Tipo int64
X2b: objeto
Em [173]: bbn[bbn.columns[:10]].dtypes
Fora[173]:
período corda
do ano Int64
do jogador Int64
equipe corda
lg corda
Int64
g ab Int64
R Int64
h Int64
Tipo Int64
X2b: objeto
Os objetos de índice não precisam ser exclusivos; você pode ter rótulos de linha ou coluna duplicados. Isso pode ser um pouco confuso
inicialmente. Se você estiver familiarizado com SQL, sabe que os rótulos de linha são semelhantes a uma chave primária em uma tabela e você
nunca queira duplicatas em uma tabela SQL. Mas uma das funções dos pandas é limpar dados confusos do mundo real antes que eles cheguem a algum lugar.
sistema a jusante. E os dados do mundo real têm duplicatas, mesmo em campos que deveriam ser únicos.
Esta seção descreve como rótulos duplicados alteram o comportamento de determinadas operações e como evitam que duplicados
surjam durante as operações, ou para detectá-los, caso surjam.
Alguns métodos pandas (Series.reindex() por exemplo) simplesmente não funcionam com duplicatas presentes. A saída não pode ser
determinado, e assim os pandas aumentam.
5033 índice,
5034 indexador,
5035 eixo = baxis,
5036 valor_preenchimento=valor_preenchimento,
5037 permitir_dups=allow_dups,
5038 copiar=copiar,
5039 )
5040 # Se já fizemos uma cópia uma vez, não há necessidade de fazer outra
5041 cópia = Falso
Outros métodos, como a indexação, podem dar resultados muito surpreendentes. Normalmente, a indexação com um escalar reduzirá a
dimensionalidade. Fatiar um DataFrame com um escalar retornará uma Série. Fatiar uma série com um escalar retornará um escalar. Mas
com duplicatas, esse não é o caso.
Em [6]: df1
Fora[6]:
AAB
0012
1345
Temos duplicatas nas colunas. Se fatiarmos 'B', receberemos de volta uma Série
Em [10]: df2
Fora[10]:
A
a0
a1
b2
a
a 1
Nome: A, dtype: int64
Você pode verificar se um índice (armazenando os rótulos de linha ou coluna) é exclusivo com Index.is_unique:
Em [13]: df2
Fora[13]:
A
um 0
um 1
b2
Nota: Verificar se um índice é exclusivo é um tanto caro para grandes conjuntos de dados. O pandas armazena esse resultado em cache,
portanto, verificar novamente o mesmo índice é muito rápido.
Em [16]: df2.index.duplicated()
Fora[16]: array([Falso, Verdadeiro, Falso])
Que pode ser usado como um filtro booleano para eliminar linhas duplicadas.
Em [17]: df2.loc[~df2.index.duplicated(),: ]
Fora[17]:
A
um 0
b2
Se você precisar de lógica adicional para lidar com rótulos duplicados, em vez de apenas descartar as repetições, usar groupby()
no índice é um truque comum. Por exemplo, resolveremos duplicatas calculando a média de todas as linhas com o mesmo rótulo.
Em [18]: df2.groupby(level=0).mean()
Fora[18]:
A a 0,5
b 2,0
Conforme observado acima, o tratamento de duplicatas é um recurso importante na leitura de dados brutos. Dito isso,
você pode evitar a introdução de duplicatas como parte de um pipeline de processamento de dados (de métodos como
pandas.concat(), rename(), etc.). Tanto Series quanto DataFrame não permitem rótulos duplicados chamando .
set_flags(allows_duplicate_labels=Falso). (o padrão é permiti-los). Se houver rótulos duplicados, uma exceção será gerada.
-------------------------------------------------- -------------------------
rótulo
b [1, 2]
Este atributo pode ser verificado ou definido comallows_duplicate_labels, que indica se aquele objeto pode ter
rótulos duplicados.
Em [22]: df
Fora[22]:
Ax0
e1
X2
A3
DataFrame.set_flags() pode ser usado para retornar um novo DataFrame com atributos comoallows_duplicate_labels definidos
com algum valor
O novo DataFrame retornado é uma visualização dos mesmos dados do antigo DataFrame. Ou a propriedade pode ser definida
diretamente no mesmo objeto
Em [27]: df2.flags.allows_duplicate_labels
Fora[27]: Falso
Ao processar dados brutos e confusos, você pode inicialmente ler os dados confusos (que potencialmente possuem rótulos duplicados),
desduplicar e, em seguida, proibir duplicatas daqui para frente, para garantir que seu pipeline de dados não introduza duplicatas.
Definir permite_duplicate_labels=True em uma série ou DataFrame com rótulos duplicados ou executar uma operação que
introduz rótulos duplicados em uma série ou DataFrame que não permite duplicatas gerará erros.
DuplicateLabelError.
Em [28]: df.rename(str.upper)
-------------------------------------------------- -------------------------
Esta mensagem de erro contém os rótulos duplicados e as posições numéricas de todas as duplicatas (incluindo
o “original”) na Série ou DataFrame
Em [30]: s1
Fora[30]:
a 0
0
tipo b: int64
rótulo
b [0, 1]
Aviso: Atualmente,Este é um
muitos recursonão
métodos experimental.
conseguem propagar o valorallows_duplicate_labels. Em versões futuras, espera-se
que cada método que receba ou retorne um ou mais objetos DataFrame ou Series propague Allows_duplicate_labels.
Esta é uma introdução ao tipo de dados categóricos do pandas, incluindo uma breve comparação com o fator R.
Categóricos são um tipo de dados pandas correspondente a variáveis categóricas em estatísticas. Uma variável categórica assume
um número limitado e geralmente fixo de valores possíveis (categorias; níveis em R). Exemplos são género, classe social, tipo
sanguíneo, afiliação ao país, tempo de observação ou classificação através de escalas Likert.
Em contraste com as variáveis categóricas estatísticas, os dados categóricos podem ter uma ordem (por exemplo, 'concordo fortemente'
vs 'concordo' ou 'primeira observação' vs. 'segunda observação'), mas as operações numéricas (adições, divisões,...) não são possível.
Todos os valores dos dados categóricos estão em categorias ou np.nan. A ordem é definida pela ordem das categorias, não pela
ordem lexical dos valores. Internamente, a estrutura de dados consiste em um array de categorias e um array inteiro de códigos
que apontam para o valor real no array de categorias.
• Uma variável de string que consiste apenas em alguns valores diferentes. Convertendo tal variável de string em uma categórica
variável economizará um pouco de memória, veja aqui.
• A ordem lexical de uma variável não é igual à ordem lógica (“um”, “dois”, “três”). Ao converter para categórico e especificar uma
ordem nas categorias, a classificação e min/max usarão a ordem lógica em vez da ordem lexical, veja aqui.
• Como um sinal para outras bibliotecas Python de que esta coluna deve ser tratada como uma variável categórica (por exemplo, para usar
métodos estatísticos ou tipos de gráficos adequados).
Criação de série
Em [2]: s
Fora[2]: 0
a
b
c
a
1 2 3 dtype: categoria
Categorias (3, objeto): ['a', 'b', 'c']
Em [5]: df
Fora[5]:
AB
0 aa 1 bb
2 cc 3 aa
Usando funções especiais, como cut(), que agrupa dados em compartimentos discretos. Veja o exemplo de ladrilho na documentação.
Em [9]: df.head(10)
Fora[9]:
valor grupo
0 65 60 - 69
1 49 40 - 49
2 56 50 - 59
3 43 40 - 49
4 43 40 - 49
5 91 90 - 99
6 32 30 - 39
7 87 80 - 89
8 36 30 - 39
9 8 0-9
Em [11]: s = pd.Series(raw_cat)
Em [12]: s
Fora[12]:
0 NaN
1 b
2 c
NaN
3 dtipo: categoria
Categorias (3, objeto): ['b', 'c', 'd']
Em [15]: df
Fora[15]:
A B
0 por NaN
1b b
2c c
3 um NaN
Em [16]: df.dtypes
Fora[16]:
A objeto
B categoria
dtype: objeto
Criação de DataFrame
Semelhante à seção anterior, onde uma única coluna foi convertida em categórica, todas as colunas em um DataFrame podem
ser convertido em lote para categórico durante ou após a construção.
Isso pode ser feito durante a construção especificando dtype="category" no construtor DataFrame:
Em [18]: df.dtypes
Fora[18]:
A categoria
B categoria
dtype: objeto
Observe que as categorias presentes em cada coluna são diferentes; a conversão é feita coluna por coluna, então apenas os rótulos estão presentes
em uma determinada coluna estão as categorias:
Em [19]: df["A"]
Fora[19]:
0 a
1 b
2 c
3 a
Nome: A, dtype: categoria
Categorias (3, objeto): ['a', 'b', 'c']
Em [20]: df["B"]
Fora[20]:
0b
1 c
2 c
3 d
Nome: B, dtype: categoria
Categorias (3, objeto): ['b', 'c', 'd']
Analogamente, todas as colunas em um DataFrame existente podem ser convertidas em lote usando DataFrame.astype():
Em [23]: df_cat.dtypes
Fora[23]:
A categoria
B categoria
dtype: objeto
Em [24]: df_cat["A"]
Fora[24]:
0 a
1 b
(continua na próxima página)
2 c
3 a
Nome: A, dtype: categoria
Categorias (3, objeto): ['a', 'b', 'c']
Em [25]: df_cat["B"]
Fora[25]:
0 b
1 c
2 c
3d
Nome: B, dtype: categoria
Categorias (3, objeto): ['b', 'c', 'd']
Controlando o comportamento
Para controlar esses comportamentos, em vez de passar 'categoria', use uma instância de CategoricalDtype.
Em [30]: s_cat
Fora[30]:
0 NaN
1b
2 c
3 NaN
tipo: categoria
Categorias (3, objeto): ['b' < 'c' < 'd']
Da mesma forma, um CategoricalDtype pode ser usado com um DataFrame para garantir que as categorias sejam consistentes entre todos
colunas.
Em [35]: df_cat["A"]
(continua na próxima página)
Fora[35]:
0 a
1 b
2 c
3 a
Nome: A, dtype: categoria
Categorias (4, objeto): ['a' < 'b' < 'c' < 'd']
Em [36]: df_cat["B"]
Fora[36]:
0b
1 c
2 c
3d
Nota: Para realizar a conversão em tabela, onde todos os rótulos em todo o DataFrame são usados como categorias para
cada coluna, o parâmetro categorias pode ser determinado programaticamente por categorias = pd.unique(df.
to_numpy().ravel()).
Se você já possui códigos e categorias, você pode usar o construtor from_codes() para salvar a etapa de fatoração
durante o modo construtor normal:
Em [40]: s
Fora[40]:
0 a
1 b
2 c
3 a
dtype: objeto
Em [41]: s2 = s.astype("categoria")
Em [42]: s2
Fora[42]:
0 a
1 b
2 c
(continua na próxima página)
a
3 dtipo: categoria
Categorias (3, objeto): ['a', 'b', 'c']
Em [43]: s2.astype(str)
Fora[43]:
0 a
1 b
2 c
3 a
dtype: objeto
Em [44]: np.asarray(s2)
Out[44]: array(['a', 'b', 'c', 'a'], dtype=objeto)
Nota: Em contraste com a função de fator de R, os dados categóricos não convertem valores de entrada em strings; as categorias
terminarão com o mesmo tipo de dados dos valores originais.
Nota: Em contraste com a função de fator de R, atualmente não há como atribuir/alterar rótulos no momento da criação. Use
categorias para alterar as categorias após o momento da criação.
Essas informações podem ser armazenadas em um CategoricalDtype. O argumento categorias é opcional, o que implica que as
categorias reais devem ser inferidas a partir de tudo o que está presente nos dados quando o pandas.Categorical é criado.
As categorias são consideradas não ordenadas por padrão.
Em [48]: CategóricoDtype()
Out[48]: CategoricalDtype(categories=Nenhum, ordenado=Falso)
Um CategoricalDtype pode ser usado em qualquer lugar onde o pandas espera um dtype. Por exemplo pandas.read_csv(), pandas.
DataFrame.astype() ou no construtor Series.
Nota: Por conveniência, você pode usar a string 'category' no lugar de CategoricalDtype quando desejar que o comportamento
padrão das categorias seja desordenado e igual aos valores definidos presentes na matriz. Em outras palavras,
Semântica de igualdade
Duas instâncias de CategoricalDtype são comparadas iguais sempre que têm as mesmas categorias e ordem. Ao comparar
duas categóricas não ordenadas, a ordem das categorias não é considerada.
Em [52]: c1 == "categoria"
Fora[52]: Verdadeiro
Aviso: como dtype='category' é essencialmente CategoricalDtype(None, False) e como todas as instâncias CategoricalDtype
são comparadas iguais a 'category', todas as instâncias de CategoricalDtype são comparadas iguais a CategoricalDtype(None,
False), independentemente das categorias ou ordenadas.
2.12.3 Descrição
Usar description() em dados categóricos produzirá uma saída semelhante a uma Series ou DataFrame do tipo string.
Em [55]: df.describe()
Fora[55]:
gatos
contar 33
frequência superior
CC
única 2 2 22
Em [56]: df["cat"].describe()
Fora[56]:
contar 3
frequência 2
c
superior única 2
Nome: gato, dtype: objeto
Os dados categóricos possuem categorias e uma propriedade ordenada, que listam seus valores possíveis e se a ordem é
importante ou não. Essas propriedades são expostas como s.cat.categories e s.cat.ordered. Se você não especificar
manualmente as categorias e a ordem, elas serão inferidas dos argumentos passados.
Nota: Novos dados categóricos não são ordenados automaticamente. Você deve passar explicitamente order=True para indicar
um categórico ordenado.
Nota: O resultado de unique() nem sempre é o mesmo que Series.cat.categories, porque Series.unique() tem algumas garantias,
nomeadamente que retorna categorias na ordem de aparição e inclui apenas valores que são realmente presente.
Em [63]: s = pd.Series(list("babc")).astype(CategoricalDtype(list("abcd")))
Em [64]: s
Fora[64]: 0
b
1 a
2 b
3 c
tipo: categoria
Categorias (4, objeto): ['a', 'b', 'c', 'd']
# categorias In
[65]: s.cat.categories Out[65]: Index(['a',
'b', 'c', 'd'], dtype='object')
# únicos em
[66]: s.unique()
Fora[66]:
['b', 'a', 'c']
Categorias (4, objeto): ['a', 'b', 'c', 'd']
Renomeando categorias
Em [68]: s
Fora[68]:
0 a
1 b
2 c
3 a
tipo: categoria
Categorias (3, objeto): ['a', 'b', 'c']
Em [70]: s
Fora[70]:
0 Grupo A
1 Grupo B
2 Grupo c
3 Grupo A
tipo: categoria
Categorias (3, objeto): ['Grupo a', 'Grupo b', 'Grupo c']
Em [72]: s
Fora[72]:
01
1 2
2 3
3 1
tipo: categoria
Categorias (3, int64): [1, 2, 3]
# Você também pode passar um objeto do tipo dict para mapear a renomeação
Em [73]: s = s.cat.rename_categories({1: "x", 2: "y", 3: "z"})
Em [74]: s
Fora[74]:
x
sim
z
x
0 1 2 3 dtipo: categoria
Categorias (3, objeto): ['x', 'y', 'z']
Nota: Em contraste com o fator R, os dados categóricos podem ter categorias de outros tipos além de string.
Nota: Esteja ciente de que atribuir novas categorias é uma operação local, enquanto a maioria das outras operações em Series.cat
por padrão, retorne uma nova série de categoria dtype.
Em [75]: tente:
....: s.cat.categories = [1, 1, 1]
....: exceto ValueError como e:
....: print("Erro de valor:", str(e))
....:
ValueError: as categorias categóricas devem ser exclusivas
Em [76]: tente:
....: s.cat.categories = [1, 2, np.nan]
....: exceto ValueError como e:
....: print("Erro de valor:", str(e))
....:
ValueError: categorias categóricas não podem ser nulas
Em [77]: s = s.cat.add_categories([4])
Em [78]: s.cat.categories
Out[78]: Índice(['x', 'y', 'z', 4], dtype='objeto')
Em [79]: s
Fora[79]:
x
sim
z
x
0 1 2 3 dtipo: categoria
Categorias (4, objeto): ['x', 'y', 'z', 4]
Removendo categorias
A remoção de categorias pode ser feita usando o método remove_categories(). Os valores removidos são substituídos por np.nan.:
Em [80]: s = s.cat.remove_categories([4])
Em [81]: s
Fora[81]:
0 x
1 sim
2 z
3 x
tipo: categoria
Categorias (3, objeto): ['x', 'y', 'z']
Em [83]: s
Fora[83]:
a
b
a
0 1 2 dtipo: categoria
Categorias (4, objeto): ['a', 'b', 'c', 'd']
Em [84]: s.cat.remove_unused_categories()
Fora[84]:
0 a
1 b
2 a
tipo: categoria
Categorias (2, objeto): ['a', 'b']
Configurando categorias
Se você quiser remover e adicionar novas categorias em uma única etapa (o que tem alguma vantagem de velocidade), ou simplesmente definir o
categorias para uma escala predefinida, use set_categories().
Em [86]: s
Fora[86]:
0 um
1 dois
quatro
-
2 3 dtipo: categoria
Categorias (4, objeto): ['-', 'quatro', 'um', 'dois']
Em [88]: s
Fora[88]:
0 um
1 dois
2 quatro
(continua na próxima página)
NaN
3 dtipo: categoria
Categorias (4, objeto): ['um', 'dois', 'três', 'quatro']
Nota: Esteja ciente de que Categorical.set_categories() não pode saber se alguma categoria foi omitida intencionalmente
ou porque está escrito incorretamente ou (no Python3) devido a uma diferença de tipo (por exemplo, NumPy S1 dtype e strings Python). Esse
pode resultar em um comportamento surpreendente!
Se os dados categóricos forem ordenados (s.cat.ordered == True), então a ordem das categorias tem um significado e certos
operações são possíveis. Se o categórico não for ordenado, .min()/.max() gerará um TypeError.
Em [90]: s.sort_values(inplace=True)
Em [92]: s.sort_values(inplace=True)
Em [93]: s
Fora[93]:
0 a
3 a
1 b
2 c
tipo: categoria
Categorias (3, objeto): ['a' < 'b' < 'c']
Você pode definir dados categóricos para serem ordenados usando as_ordered() ou não ordenados usando as_unordered(). Esses
por padrão retornará um novo objeto.
Em [95]: s.cat.as_ordered()
Fora[95]:
0 a
a
31 b
2 c
tipo: categoria
Categorias (3, objeto): ['a' < 'b' < 'c']
Em [96]: s.cat.as_unordered()
Fora[96]:
0 a
3 a
(continua na próxima página)
1 b
2 c
tipo: categoria
Categorias (3, objeto): ['a', 'b', 'c']
A classificação usará a ordem definida pelas categorias, e não qualquer ordem lexical presente no tipo de dados. Isto é verdade até para
strings e dados numéricos:
Em [99]: s
Fora[99]:
01
1 2
2 3
1
3 dtipo: categoria
Categorias (3, int64): [2 <3 <1]
Em [100]: s.sort_values(inplace=True)
Em [101]: s
Fora[101]:
1 2
2 3
0 1
1
3 dtipo: categoria
Categorias (3, int64): [2 <3 <1]
Reordenando
Em [105]: s
Fora[105]:
0 1
1 2
2 3
(continua na próxima página)
1
3 dtipo: categoria
Categorias (3, int64): [2 <3 <1]
Em [106]: s.sort_values(inplace=True)
Em [107]: s
Fora[107]:
1 2
2 3
1
1
0 3 dtipo: categoria
Categorias (3, int64): [2 <3 <1]
Nota: Observe a diferença entre atribuir novas categorias e reordenar as categorias: a primeira renomeia as categorias
e, portanto, os valores individuais na Série, mas se a primeira posição foi classificada por último, o valor renomeado ainda será
ser classificado por último. Reordenar significa que a forma como os valores são classificados é diferente posteriormente, mas não que os valores individuais
na Série são alterados.
Nota: Se o Categórico não estiver ordenado, Series.min() e Series.max() gerarão TypeError. Numérico
operações como +, -, *, / e operações baseadas nelas (por exemplo, Series.median(), que precisariam calcular o
média entre dois valores se o comprimento de uma matriz for par) não funcionam e geram um TypeError.
Uma coluna de tipo categórico participará de uma classificação de múltiplas colunas de maneira semelhante a outras colunas. A encomenda
do categórico é determinado pelas categorias dessa coluna.
3e2
7a1
6a2
0b1
5b 1 1b
2 4b 2
1b2
4b2
2e1
3e2
2.12.6 Comparações
• Comparar a igualdade (== e !=) com um objeto semelhante a uma lista (lista, série, array, . . . ) do mesmo comprimento que o categórico
dados.
• Todas as comparações (==, !=, >, >=, < e <=) de dados categóricos com outra série categórica, quando
ordenado==Verdadeiro e as categorias são iguais.
• Todas as comparações de dados categóricos com dados escalares.
Todas as outras comparações, especialmente comparações de “não igualdade” de dois categóricos com categorias diferentes ou de um categórico
com qualquer objeto semelhante a uma lista, gerarão um TypeError.
Nota: Qualquer comparação de “não igualdade” de dados categóricos com uma série, np.array, lista ou dados categóricos com
categorias ou ordenações diferentes gerará um TypeError porque a ordenação de categorias personalizadas pode ser interpretada
de duas maneiras: uma levando em consideração o ordenando e um sem.
Em [116]: gato
(continua na próxima página)
Fora[116]:
0 1
1 2
2 3
tipo: categoria
Categorias (3, int64): [3 <2 <1]
Em [117]: cat_base
Fora[117]:
0 2
2
2
1 2 dtipo: categoria
Categorias (3, int64): [3 <2 <1]
Em [118]: cat_base2
Fora[118]:
02
12
22
tipo: categoria
Categorias (1, int64): [2]
Comparar com um categórico com as mesmas categorias e ordenação ou com um escalar funciona:
Falso
Falso
1 2 dtype: bool
1 Falso
2 Falso
tipo d: bool
As comparações de igualdade funcionam com qualquer objeto semelhante a uma lista de mesmo comprimento e escalares:
2 Falso
tipo d: bool
1 Verdadeiro
tipo d: bool
Em [123]: gato == 2
Fora[123]:
0 Falso
1 Verdadeiro
2 Falso
tipo d: bool
Em [124]: tente:
.....: gato > gato_base2
.....: exceto TypeError como e:
.....: print("TypeError:", str(e))
.....:
TypeError: categóricos só podem ser comparados se as 'categorias' forem iguais.
Se você quiser fazer uma comparação de “não igualdade” de uma série categórica com um objeto semelhante a uma lista que não é categórico
dados, você precisa ser explícito e converter os dados categóricos de volta aos valores originais:
Em [126]: tente:
.....: gato > básico
.....: exceto TypeError como e:
.....: print("TypeError:", str(e))
.....:
TypeError: Não é possível comparar um categórico para op __gt__ com o tipo <class 'numpy.ndarray'>.
Se você quiser comparar valores, use 'np.asarray(cat) <op> other'.
Quando você compara duas categóricas não ordenadas com as mesmas categorias, a ordem não é considerada:
Em [130]: c1 == c2
Fora[130]: array([ Verdadeiro, Verdadeiro])
2.12.7 Operações
Além de Series.min(), Series.max() e Series.mode(), as seguintes operações são possíveis com dados categóricos:
Métodos de série como Series.value_counts() usarão todas as categorias, mesmo que algumas categorias não estejam presentes no
dados:
Em [132]: s.value_counts()
Fora[132]:
c 2
a 1
1
0
bd tipo: int64
Em [134]: df = pd.DataFrame(
.....: dados=[[1, 2, 3], [4, 5, 6]],
.....: colunas=pd.MultiIndex.from_arrays([["A", "B", "B"], colunas]),
..... :)
.....:
Em [138]: df.groupby("gatos").mean()
Fora[138]:
valores
gatos
a 1,0
b 2,0
c 4,0
(continua na próxima página)
Tabelas dinâmicas:
Em [143]: df = pd.DataFrame({"A": raw_cat, "B": ["c", "d", "c", "d"], "valores": [1, 2, 3 ,
ÿÿ 4]})
Os métodos otimizados de acesso a dados do pandas .loc, .iloc, .at e .iat funcionam normalmente. A única diferença é o
tipo de retorno (para obtenção) e que apenas valores já em categorias podem ser atribuídos.
Recebendo
Se a operação de fatiamento retornar um DataFrame ou uma coluna do tipo Series, a categoria dtype será preservada.
Em [146]: cats = pd.Series(["a", "b", "b", "b", "c", "c", "c"], dtype="category",ÿ
ÿÿíndice=idx)
Em [149]: df.iloc[2:4,: ]
Fora[149]:
valores de gatos
b 2
brincadeira b 2
Um exemplo em que o tipo de categoria não é preservado é se você pegar uma única linha: a série resultante é do tipo d
objeto:
valores 1
Nome: h, dtype: objeto
Retornar um único item de dados categóricos também retornará o valor, não um categórico de comprimento “1”.
Em [154]: df.iat[0, 0]
Fora[154]: 'a'
Nota: A está em contraste com a função de fator de R, onde factor(c(1,2,3))[1] retorna um fator de valor único.
Para obter uma série de valor único do tipo categoria, você passa uma lista com um único valor:
Em [160]: str_cat
Fora[160]:
0 a
1 a
2 b
3 b
tipo: categoria
Categorias (2, objeto): ['a', 'b']
Em [161]: str_cat.str.contains("a")
Fora[161]:
0 Verdadeiro
1 Verdadeiro
2 Falso
3 Falso
tipo d: bool
Em [164]: data_cat
Fora[164]:
0 01/01/2015
12015-01-02
2 03/01/2015
3 04/01/2015
4 05/01/2015
tipo: categoria
Categorias (5, datetime64[ns]): [2015-01-01, 2015-01-02, 2015-01-03, 2015-01-04, 2015-01- ÿÿ05]
Nota: A Série retornada (ou DataFrame) é do mesmo tipo como se você usasse .str.<method> / .dt.<method> em uma Série
desse tipo (e não da categoria de tipo!).
Isso significa que os valores retornados dos métodos e propriedades dos acessadores de uma Série e os valores retornados dos
métodos e propriedades dos acessadores desta Série transformados para um do tipo categoria serão iguais:
1 Verdadeiro
2 Verdadeiro
3 Verdadeiro
tipo d: bool
Nota: O trabalho é feito nas categorias e em seguida é construída uma nova Série. Isso tem algumas implicações no desempenho
se você tiver uma Série do tipo string, onde muitos elementos são repetidos (ou seja, o número de elementos únicos na Série é
muito menor que o comprimento da Série). Nesse caso, pode ser mais rápido converter a série original em uma categoria de tipo
e usar .str.<method> ou .dt.<property> nisso.
Contexto
Definir valores em uma coluna categórica (ou série) funciona desde que o valor esteja incluído nas categorias:
Em [171]: gatos = pd.Categorical(["a", " a", "a", "a", "a", "a", "a"], categorias=["a", "b
ÿÿ"])
Em [175]: df
Fora[175]:
valores de gatos
a 1
a 1
2
bb 2
hijkl a 1
mãe 1
n a 1
Em [176]: tente:
.....: df.iloc[2:4, :] = [["c", 3], ["c", 3]]
.....: exceto TypeError como e:
.....: print("TypeError:", str(e))
.....:
TypeError: Não é possível definir o item em um categórico com uma nova categoria, defina as categorias primeiro
Em [178]: df
Fora[178]:
valores de gatos
a 1
a 1
a 2
a 2
hijkl a 1
mãe 1
n a 1
Em [179]: tente:
.....: df.loc["j":"k", "gatos"] = pd.Categorical(["b", "b"], categorias=["a", "b",
ÿÿ"c"])
.....: exceto TypeError como e:
.....: print("TypeError:", str(e))
.....:
(continua na próxima página)
TypeError: Não é possível definir um Categórico com outro, sem categorias idênticas
Em [180]: df = pd.DataFrame({"a": [1, 1, 1, 1, 1], "b": ["a", "a", "a", "a", " a"]})
Em [183]: df
Fora[183]:
ab 0
1 a 1 ba
2 bb 3 1
b
4 1 uma
In [184]: df.dtypes
Out[184]:
a objeto
b objeto dtype:
objeto
Mesclagem/concatenação
Por padrão, combinar Series ou DataFrames que contêm as mesmas categorias resulta em categoria dtype, caso contrário, os
resultados dependerão do dtype das categorias subjacentes. As mesclagens que resultam em dtypes não categóricos
provavelmente terão maior uso de memória. Use .astype ou union_categoricals para garantir resultados de categoria.
# mesmas categorias
em [186]: s1 = pd.Series(["a", "b"], dtype="category")
# categorias diferentes em
[189]: s3 = pd.Series(["b", "c"], dtype="category")
Consulte também a seção sobre tipos de mesclagem para notas sobre como preservar tipos de mesclagem e desempenho.
União
Se você deseja combinar categóricos que não possuem necessariamente as mesmas categorias, a função
union_categoricals() combinará uma lista de categóricos. As novas categorias serão a união das categorias que estão sendo combinadas.
Por padrão, as categorias resultantes serão ordenadas conforme aparecem nos dados. Se você deseja que as categorias sejam ordenadas
por lex, use o argumento sort_categories=True.
union_categoricals também funciona com o caso “fácil” de combinar duas categóricas das mesmas categorias e informações
de pedido (por exemplo, o que você também pode acrescentar).
O exemplo abaixo gera TypeError porque as categorias são ordenadas e não idênticas.
Categóricos ordenados com diferentes categorias ou ordenações podem ser combinados usando o argumento
ignore_ordered=True.
union_categoricals() também funciona com um CategoricalIndex, ou Série contendo dados categóricos, mas observe
que o array resultante será sempre um Categorical simples:
Nota: union_categoricals pode recodificar os códigos inteiros para categorias ao combinar categóricos. Provavelmente é isso
que você deseja, mas se estiver contando com a numeração exata das categorias, fique atento.
Em [212]: c1
Fora[212]:
['b', 'c']
Categorias (2, objeto): ['b', 'c']
Em [214]: c2
Fora[214]:
['a', 'b']
Categorias (2, objeto): ['a', 'b']
Em [217]: c
Fora[217]:
['b', 'c', 'a', 'b']
Categorias (3, objeto): ['b', 'c', 'a']
Você pode gravar dados que contenham tipos de categoria em um HDFStore. Veja aqui um exemplo e advertências.
Também é possível gravar e ler dados de arquivos no formato Stata . Veja aqui um exemplo e advertências.
Gravar em um arquivo CSV converterá os dados, removendo efetivamente qualquer informação sobre o categórico (categorias e
encomenda). Portanto, se você reler o arquivo CSV, deverá converter as colunas relevantes de volta para a categoria e atribuir o
categorias corretas e ordenação de categorias.
Em [219]: importar io
#renomeie as categorias
Em [221]: s.cat.categories = ["muito bom", "bom", "ruim"]
Em [225]: df.to_csv(csv)
Em [227]: df2.dtypes
Fora[227]:
Sem nome: 0 int64
gatos objeto
vals int64
dtype: objeto
Em [228]: df2["gatos"]
Fora[228]:
0 muito bom
1 bom
2 bom
3 muito bom
4 muito bom
5 ruim
Nome: gatos, dtype: objeto
# Refaça a categoria
Em [229]: df2["cats"] = df2["cats"].astype("category")
Em [230]: df2["cats"].cat.set_categories(
.....: ["muito ruim", "ruim", "médio", "bom", "muito bom"], inplace=True
..... :)
.....:
Em [231]: df2.dtypes
(continua na próxima página)
Fora[231]:
Sem nome: 0 int64
gatos categoria
vals int64
dtype: objeto
Em [232]: df2["gatos"]
Fora[232]:
0 muito bom
1 bom
2 bom
3 muito bom
4 muito bom
5 ruim
Nome: gatos, dtype: categoria
Categorias (5, objeto): ['muito ruim', 'ruim', 'médio', 'bom', 'muito bom']
pandas usa principalmente o valor np.nan para representar dados ausentes. Por padrão, não é incluído nos cálculos. Ver
a seção Dados ausentes.
Os valores faltantes não devem ser incluídos nas categorias da Categórica, apenas nos valores. Em vez disso, entende-se
que NaN é diferente e é sempre uma possibilidade. Ao trabalhar com códigos categóricos, os valores faltantes serão
sempre tenha um código de -1.
Em [235]: s.cat.codes
Fora[235]:
00
11
2 -1
30
tipo d: int8
Métodos para trabalhar com dados faltantes, por exemplo, isna(), fillna(), dropna(), todos funcionam normalmente:
Em [237]: s
Fora[237]: 0
a
1 b
2 NaN
tipo: categoria
Categorias (2, objeto): ['a', 'b']
Em [238]: pd.isna(s)
Out[238]: 0
Falso 1 Falso
2 dtype: bool
Verdadeiro
Em [239]: s.fillna("a")
Out[239]: 0
a
b
a
1 2 dtype: categoria
Categorias (2, objeto): ['a', 'b']
• Os níveis do R são sempre do tipo string, enquanto as categorias no pandas podem ser de qualquer tipo.
• Em contraste com a função fatorial de R, usar dados categóricos como a única entrada para criar uma nova série categórica não
removerá categorias não utilizadas, mas criará uma nova série categórica que é igual à passada em uma!
• R permite que valores faltantes sejam incluídos em seus níveis (categorias de pandas). pandas não permite NaN
categorias, mas valores ausentes ainda podem estar nos valores.
2.12.12 Pegadinhas
Uso de memória
O uso de memória de um Categórico é proporcional ao número de categorias mais o comprimento dos dados. Por outro lado, um dtype
de objeto é uma constante vezes o comprimento dos dados.
# objeto dtype In
[241]: s.nbytes Out[241]:
16000
# categoria dtype In
[242]: s.astype("categoria").nbytes Out[242]: 2016
Nota: Se o número de categorias se aproximar do comprimento dos dados, o Categórico usará quase a mesma ou mais
memória do que uma representação de tipo de objeto equivalente.
# objeto dtype In
[244]: s.nbytes Out[244]:
16000
# categoria dtype In
[245]: s.astype("categoria").nbytes Out[245]:
20000
Atualmente, os dados categóricos e o Categorical subjacente são implementados como um objeto Python e não como um dtype de
array NumPy de baixo nível. Isso leva a alguns problemas.
Em [246]: tente:
.....: np.dtype("category") .....:
exceto TypeError as e:
.....: print("TypeError:", str(e))
.....:
TypeError: tipo de dados 'categoria' não compreendido
Em [248]: tente:
.....: np.dtype(dtype) .....:
exceto TypeError as e:
.....: print("TypeError:", str(e))
.....:
TypeError: Não é possível interpretar 'CategoricalDtype(categories=['a'], ordenado=False)' como umÿ ÿÿtipo de
dados
Para verificar se uma série contém dados categóricos, use hasattr(s, 'cat'):
Usar funções NumPy em uma série de categoria de tipo não deve funcionar, pois categóricos não são dados numéricos (mesmo
no caso de .categories ser numérico).
Em [254]: tente:
.....: np.soma(s)
.....: exceto TypeError como e:
.....: print("TypeError:", str(e))
.....:
TypeError: 'Categorical' com categoria dtype não suporta redução 'soma'
digite aplicar
Atualmente, o pandas não preserva o dtype nas funções de aplicação: se você aplicar ao longo das linhas, obterá uma série de objetos
dtype (o mesmo que obter uma linha -> obter um elemento retornará um tipo básico) e aplicar ao longo das colunas também
converter em objeto. Os valores NaN não são afetados. Você pode usar fillna para lidar com valores ausentes antes de aplicar uma função.
Em [255]: df = pd.DataFrame(
.....: {
.....: "uma": [1, 2, 3, 4],
.....: "b": ["a", "b", "c", "d"],
.....: "gatos": pd.Categorical([1, 2, 3, 2]),
.....: }
..... :)
.....:
Índice categórico
CategoricalIndex é um tipo de índice útil para oferecer suporte à indexação com duplicatas. Este é um contêiner em torno de um
Categórico e permite a indexação e armazenamento eficiente de um índice com um grande número de elementos duplicados. Consulte
a documentação de indexação avançada para uma explicação mais detalhada.
Efeitos colaterais
Construir uma série a partir de um categórico não copiará a entrada categórica. Isso significa que as alterações na Série irão,
na maioria dos casos, alterar a Categórica original:
Em [266]: gato
Fora[266]:
[1, 2, 3, 10]
Categorias (5, int64): [1, 2, 3, 4, 10]
Em [267]: s.iloc[0:2] = 10
Em [268]: gato
Fora[268]:
[10, 10, 3, 10]
Categorias (5, int64): [1, 2, 3, 4, 10]
Em [269]: df = pd.DataFrame(s)
Em [271]: gato
Fora[271]:
[10, 10, 3, 10]
Categorias (5, int64): [1, 2, 3, 4, 10]
Use copy=True para evitar tal comportamento ou simplesmente não reutilize categóricos:
Em [274]: gato
Fora[274]:
[1, 2, 3, 10]
Categorias (5, int64): [1, 2, 3, 4, 10]
Em [275]: s.iloc[0:2] = 10
Em [276]: gato
Fora[276]:
[1, 2, 3, 10]
Categorias (5, int64): [1, 2, 3, 4, 10]
Nota: Isso também acontece em alguns casos quando você fornece um array NumPy em vez de um Categórico: usar um
array int (por exemplo, np.array([1,2,3,4])) exibirá o mesmo comportamento, enquanto usa uma string array (por exemplo,
np.array(["a","b", "c","a"])) não.
Nota: IntegerArray é atualmente experimental. Sua API ou implementação pode mudar sem aviso prévio.
Alterado na versão 1.0.0: agora usa pandas.NA como valor ausente em vez de numpy.nan.
Em Trabalhando com dados ausentes, vimos que o pandas usa principalmente NaN para representar dados ausentes. Como NaN é um ponto
flutuante, isso força uma matriz de números inteiros com quaisquer valores ausentes a se tornar um ponto flutuante. Em alguns casos, isso pode não
importar muito. Mas se a sua coluna inteira for, digamos, um identificador, a conversão para float pode ser problemática. Alguns inteiros nem sequer
podem ser representados como números de ponto flutuante.
2.13.1 Construção
pandas pode representar dados inteiros com valores possivelmente ausentes usando arrays.IntegerArray. Este é um tipo de
extensão implementado no pandas.
Em [2]: arr
Fora[2]:
<ArrayInteiro>
[1, 2, <NA>]
Comprimento: 3, tipo d: Int64
Ou o alias de string "Int64" (observe o "I" maiúsculo, para diferenciar do dtype 'int64' do NumPy:
Este array pode ser armazenado em um DataFrame ou Series como qualquer array NumPy.
Em [5]: pd.Series(arr)
Fora[5]: 0
1
1 2
2 <NA>
tipo de d: Int64
Você também pode passar o objeto semelhante a uma lista para o construtor Series com o dtype.
Aviso: atualmente pandas.array() e pandas.Series() usam regras diferentes para inferência de dtype. pandas. array() inferirá
um tipo de número inteiro anulável
Para compatibilidade com versões anteriores, Series infere-os como tipo inteiro ou tipo flutuante
tipo d: int64
No futuro, poderemos fornecer uma opção para Series inferir um dtype inteiro anulável.
2.13.2 Operações
As operações envolvendo uma matriz inteira se comportarão de maneira semelhante às matrizes NumPy. Valores ausentes serão propagados e o
os dados serão coagidos para outro dtype, se necessário.
# aritmética
Em [13]: s + 1
Fora[13]:
0 2
1 3
2 <NA>
tipo de d: Int64
# comparação
Em [14]: s == 1
Fora[14]:
Verdadeiro
Falso
<NA>
0 1 2 dtype: booleano
# indexação
Em [15]: s.iloc[1:3]
Fora[15]:
1 2
2 <NA>
tipo de d: Int64
Em [19]: df
Fora[19]:
abc
0 1 1 uma
1 2 1 uma
2 <NA> 3 b
Em [20]: df.dtypes
Fora[20]:
Um Int64
B int64
Objeto C
dtype: objeto
Em [22]: df["A"].astype(float)
Fora[22]:
(continua na próxima página)
0 1,0
1 2,0
2 NaN
Nome: A, tipo d: float64
Em [23]: df.sum()
Fora[23]:
A 3
B 5
aab
Tipo de C: objeto
Em [24]: df.groupby("B").A.sum()
Fora[24]:
B
1 3
30
arrays.IntegerArray usa pandas.NA como seu valor escalar ausente. Fatiar um único elemento que está faltando irá
retornar pandas.NA
Em [26]: uma[1]
Fora[26]: <NA>
Nota: BooleanArray é atualmente experimental. Sua API ou implementação pode mudar sem aviso prévio.
pandas permite a indexação com valores NA em uma matriz booleana, que são tratados como False.
Em [3]: s[máscara]
Fora[3]:
01
tipo d: int64
Se preferir manter os valores NA, você pode preenchê-los manualmente com fillna(True).
Em [4]: s[mask.fillna(True)]
Fora[4]:
01
23
tipo d: int64
arrays.BooleanArray implementa Kleene Logic (às vezes chamada de lógica de três valores) para operações lógicas como &
(e), | (ou) e ^ (exclusivo-ou).
Esta tabela demonstra os resultados para cada combinação. Essas operações são simétricas, portanto, invertendo os lados esquerdo e
lado direito não faz diferença no resultado.
Expressão Resultado
NA | N / D N/D
NA ^ NA N/D
Quando um NA está presente em uma operação, o valor de saída será NA somente se o resultado não puder ser determinado apenas com base em
a outra entrada. Por exemplo, Verdadeiro | NA é Verdadeiro, porque tanto Verdadeiro | Verdadeiro e Verdadeiro | Falso é Verdadeiro. Naquilo
Neste caso, não precisamos realmente considerar o valor de NA.
Por outro lado, Verdadeiro e NA é NA. O resultado depende se o NA é realmente Verdadeiro ou Falso, uma vez que Verdadeiro e
True é True, mas True & False é False, portanto não podemos determinar a saída.
Isso difere de como o np.nan se comporta em operações lógicas. pandas tratados np.nan é sempre falso na saída.
Em ou
1 Verdadeiro
2 Falso
tipo d: bool
Verdadeiro
Verdadeiro
0 1 2 dtype: booleano
dentro e
1 Falso
2 Falso
tipo d: bool
Falso
<NA>
1 2 dtype: booleano
{{cabeçalho}}
Esta seção demonstra a visualização por meio de gráficos. Para obter informações sobre visualização de dados tabulares, consulte
a seção sobre Visualização de Tabela.
Em [2]: plt.close("todos")
Fornecemos o básico em pandas para criar facilmente gráficos de aparência decente. Veja a seção do ecossistema para visualização
bibliotecas que vão além do básico documentado aqui.
Em [4]: ts = ts.cumsum()
Em [5]: ts.plot();
Se o índice consistir em datas, ele chama gcf().autofmt_xdate() para tentar formatar bem o eixo x conforme acima.
No DataFrame, plot() é uma conveniência para plotar todas as colunas com rótulos:
Em [7]: df = df.cumsum()
Em [8]: plt.figure();
Em [9]: df.plot();
Você pode plotar uma coluna versus outra usando as palavras-chave x e y em plot():
Nota: Para obter mais opções de formatação e estilo, consulte formatação abaixo.
Os métodos de plotagem permitem vários estilos de plotagem além do gráfico de linha padrão. Esses métodos podem ser fornecidos como argumento de palavra-chave kind
para plot() e incluem:
Em [13]: plt.figure();
Em [14]: df.iloc[5].plot(kind="bar");
Você também pode criar esses outros gráficos usando os métodos DataFrame.plot.<kind> em vez de fornecer o tipo
argumento de palavra-chave. Isso torna mais fácil descobrir os métodos de plotagem e os argumentos específicos que eles usam:
Em [15]: df = pd.DataFrame()
Além desses kind s, existem os métodos DataFrame.hist() e DataFrame.boxplot() , que usam um método separado.
interface.
Finalmente, existem várias funções de plotagem em pandas.plotting que usam uma Série ou DataFrame como argumento.
Esses incluem:
• Matriz de Dispersão
• Curvas de Andrews
• Coordenadas Paralelas
• Gráfico de atraso
• Gráfico de autocorrelação
• Gráfico de inicialização
• RadViz
Gráficos de barras
Para dados rotulados e não de séries temporais, você pode querer produzir um gráfico de barras:
Em [17]: plt.figure();
Em [18]: df.iloc[5].plot.bar();
Em [21]: df2.plot.bar();
Em [22]: df2.plot.bar(stacked=True);
Em [23]: df2.plot.barh(stacked=True);
Histogramas
Em [25]: plt.figure();
Em [26]: df4.plot.hist(alfa=0,5);
Um histograma pode ser empilhado usando stacked=True. O tamanho do compartimento pode ser alterado usando a palavra-chave bins.
Em [27]: plt.figure();
Você pode passar outras palavras-chave suportadas pelo matplotlib hist. Por exemplo, histogramas horizontais e cumulativos podem
ser desenhados por orientação='horizontal' e cumulativo=True.
Em [29]: plt.figure();
Consulte o método hist e a documentação hist do matplotlib para obter mais informações.
A interface existente DataFrame.hist para traçar o histograma ainda pode ser usada.
Em [31]: plt.figure();
Em [32]: df["A"].diff().hist();
Em [33]: plt.figure();
Gráficos de caixa
Boxplot pode ser desenhado chamando Series.plot.box() e DataFrame.plot.box(), ou DataFrame.boxplot() para visualizar a distribuição
de valores dentro de cada coluna.
Por exemplo, aqui está um boxplot representando cinco tentativas de 10 observações de uma variável aleatória uniforme em [0,1).
Em [40]: df.plot.box();
O Boxplot pode ser colorido passando a palavra-chave color. Você pode passar um ditado cujas chaves são caixas, bigodes, medianas
e bonés. Se algumas chaves estiverem faltando no dicionário, as cores padrão serão usadas para os artistas correspondentes. Além disso, boxplot
possui a palavra-chave sym para especificar o estilo dos panfletos.
Quando você passa outro tipo de argumento por meio da palavra-chave color, ele será passado diretamente para matplotlib para todas as caixas,
coloração de bigodes, medianas e gorros.
As cores são aplicadas a todas as caixas a serem desenhadas. Se você quiser uma colorização mais complicada, você pode desenhar cada um
artistas passando return_type.
Em [41]: cor = {
....: "caixas": "VerdeEscuro",
....: "bigodes": "Laranja Escuro",
....: "medianas": "Azul Escuro",
....: "caps": "Cinza",
....: }
....:
Além disso, você pode passar outras palavras-chave suportadas pelo boxplot matplotlib. Por exemplo, boxplot horizontal e com posicionamento
personalizado podem ser desenhados por vert=False e posições palavras-chave.
Consulte o método boxplot e a documentação do boxplot matplotlib para obter mais informações.
A interface existente DataFrame.boxplot para plotar boxplot ainda pode ser usada.
Em [45]: plt.figure();
Em [46]: bp = df.boxplot()
Você pode criar um boxplot estratificado usando o argumento by palavra-chave para criar agrupamentos. Por exemplo,
Em [48]: df["X"] = pd.Series(["A", "A", "A ", "A", "A", " B", "B", "B", " B", "B"])
Em [49]: plt.figure();
Em [50]: bp = df.boxplot(by="X")
Você também pode passar um subconjunto de colunas para plotar, bem como agrupar por múltiplas colunas:
Em [52]: df["X"] = pd.Series(["A", "A", "A ", "A", "A", " B", "B", "B", " B", "B"])
Em [53]: df["Y"] = pd.Series(["A", "B", "A", "B", "A", "B", " A", "B", " A", "B"])
Em [54]: plt.figure();
Em [57]: df["X"] = pd.Series(["A", "A", "A ", "A", "A", " B", "B", "B", " B", "B"])
Em [58]: plt.figure();
No boxplot, o tipo de retorno pode ser controlado pela palavra-chave return_type. As escolhas válidas são {"axes", "dict
", "both", None}. A facetação, criada por DataFrame.boxplot com a palavra-chave by, afetará o tipo de saída como
bem:
Em [60]: np.random.seed(1234)
Em [64]: bp = df_box.boxplot(by="g")
As subparcelas acima são divididas primeiro pelas colunas numéricas e depois pelo valor da coluna g. Abaixo, as subparcelas são
primeiro divididas pelo valor de g e depois pelas colunas numéricas.
Em [65]: bp = df_box.groupby("g").boxplot()
Gráfico de área
Você pode criar gráficos de área com Series.plot.area() e DataFrame.plot.area(). Os gráficos de área são empilhados por padrão. Para
produzir um gráfico de área empilhada, cada coluna deve ter todos valores positivos ou negativos.
Quando os dados de entrada contiverem NaN, eles serão preenchidos automaticamente com 0. Se você quiser eliminar ou preencher com
valores diferentes, use dataframe.dropna() ou dataframe.fillna() antes de chamar plot.
Em [67]: df.plot.area();
Para produzir um gráfico não empilhado, passe stacked=False. O valor alfa é definido como 0,5, salvo especificação em contrário:
Em [68]: df.plot.area(stacked=False);
Gráfico de dispersão
O gráfico de dispersão pode ser desenhado usando o método DataFrame.plot.scatter(). O gráfico de dispersão requer colunas
numéricas para os eixos x e y. Eles podem ser especificados pelas palavras-chave xey.
Para plotar vários grupos de colunas em um único eixo, repita o método de plotagem especificando o eixo de destino. Recomenda-se
especificar palavras-chave de cor e rótulo para distinguir cada grupo.
A palavra-chave c pode ser fornecida como o nome de uma coluna para fornecer cores para cada ponto:
Se uma coluna categórica for passada para c, uma barra de cores discreta será produzida:
Você pode passar outras palavras-chave suportadas pelo scatter matplotlib. O exemplo abaixo mostra um gráfico de bolhas usando
uma coluna do DataFrame como tamanho da bolha.
Consulte o método de dispersão e a documentação de dispersão do matplotlib para obter mais informações.
Você pode criar gráficos bin hexagonais com DataFrame.plot.hexbin(). Os gráficos hexbin podem ser uma alternativa útil aos gráficos de
dispersão se seus dados forem muito densos para representar cada ponto individualmente.
Um argumento de palavra-chave útil é gridsize; ele controla o número de hexágonos na direção x e o padrão é 100.
Um tamanho de grade maior significa mais caixas menores.
Por padrão, um histograma das contagens em torno de cada ponto (x, y) é calculado. Você pode especificar agregações alternativas
passando valores para os argumentos C e reduzir_C_function. C especifica o valor em cada ponto (x, y) e reduzir_C_função é uma
função de um argumento que reduz todos os valores em um compartimento a um único número (por exemplo, média, máximo, soma,
padrão). Neste exemplo as posições são dadas pelas colunas a e b, enquanto o valor é dado pela coluna z. As caixas são agregadas
com a função max do NumPy.
Consulte o método hexbin e a documentação hexbin do matplotlib para obter mais informações.
Gráfico de torta
Você pode criar um gráfico de pizza com DataFrame.plot.pie() ou Series.plot.pie(). Se seus dados incluírem qualquer NaN, eles
serão preenchidos automaticamente com 0. Um ValueError será gerado se houver algum valor negativo em seus dados.
Em [84]: série = pd.Series(3 * np.random.rand(4), index=["a", "b", "c", "d"], nome= ÿÿ"série")
Para gráficos de pizza, é melhor usar figuras quadradas, ou seja, uma proporção de figura 1. Você pode criar a figura com
largura e altura iguais ou forçar a proporção a ser igual após a plotagem chamando ax.set_aspect('equal') no objeto de eixos
retornado.
Observe que o gráfico de pizza com DataFrame requer que você especifique uma coluna de destino pelo argumento y ou subplots=True.
Quando y é especificado, o gráfico de pizza da coluna selecionada será desenhado. Se subplots=True for especificado, os gráficos de pizza
para cada coluna serão desenhados como subgráficos. Uma legenda será desenhada em cada gráfico de pizza por padrão; especifique
legend=False para ocultá-lo.
Em [86]: df = pd.DataFrame( 3 *
....: np.random.rand(4, 2), index=["a", "b", "c", "d"], colunas=["x" , "você"]
....: )
....:
Você pode usar as palavras-chave rótulos e cores para especificar os rótulos e cores de cada fatia.
Aviso: a maioria dos gráficos de pandas usa os argumentos rótulo e cor (observe a falta de “s” neles). Para ser consistente
com matplotlib.pyplot.pie() você deve usar rótulos e cores.
Se desejar ocultar rótulos de fatia, especifique rótulos=Nenhum. Se fontsize for especificado, o valor será aplicado à cunha
rótulos. Além disso, outras palavras-chave suportadas por matplotlib.pyplot.pie() podem ser usadas.
Em [88]: series.plot.pie(
....: rótulos=["AA", "BB", "CC", "DD"],
....: cores=["r", "g", "b", "c"],
....: autopct="%.2f",
....: tamanho da fonte=20,
....: tamanho da figura=(6, 6),
....: );
....:
Se você passar valores cuja soma total seja menor que 1,0, o matplotlib desenha um semicírculo.
O pandas tenta ser pragmático ao traçar DataFrames ou séries que contêm dados ausentes. Os valores ausentes são eliminados, omitidos ou preenchidos
dependendo do tipo de gráfico.
Se algum desses padrões não for o que você deseja ou se quiser ser explícito sobre como os valores ausentes são tratados,
considere usar fillna() ou dropna() antes de plotar.
Essas funções podem ser importadas de pandas.plotting e usar uma Série ou DataFrame como argumento.
Você pode criar uma matriz de gráfico de dispersão usando o método scatter_matrix em pandas.plotting:
Gráfico de densidade
Em [95]: ser.plot.kde();
Curvas de Andrews
As curvas de Andrews permitem traçar dados multivariados como um grande número de curvas que são criadas usando os atributos de
amostras como coeficientes para séries de Fourier, consulte a entrada da Wikipedia para obter mais informações. Ao colorir essas curvas
de forma diferente para cada classe é possível visualizar o agrupamento de dados. Curvas pertencentes a amostras da mesma classe
geralmente estarão mais próximas e formarão estruturas maiores.
Em [98]: plt.figure();
Coordenadas paralelas
Coordenadas paralelas são uma técnica de plotagem para plotar dados multivariados; consulte a entrada da Wikipedia para obter uma introdução.
Coordenadas paralelas permitem ver clusters de dados e estimar outras estatísticas visualmente. Usando coordenadas paralelas, os
pontos são representados como segmentos de linha conectados. Cada linha vertical representa um atributo. Um conjunto de segmentos
de linha conectados representa um ponto de dados. Os pontos que tendem a se agrupar aparecerão mais próximos.
Em [102]: plt.figure();
Gráfico de atraso
Os gráficos de atraso são usados para verificar se um conjunto de dados ou série temporal é aleatório. Os dados aleatórios não devem exibir
nenhuma estrutura no gráfico de defasagem. A estrutura não aleatória implica que os dados subjacentes não são aleatórios. O argumento lag
pode ser passado, e quando lag=1 o gráfico é essencialmente data[:-1] vs. data[1:].
Em [105]: plt.figure();
Em [108]: lag_plot(dados);
Gráfico de autocorrelação
Gráficos de autocorrelação são frequentemente usados para verificar a aleatoriedade em séries temporais. Isso é feito calculando autocorrelações
para valores de dados em intervalos de tempo variados. Se a série temporal for aleatória, tais autocorrelações deverão ser próximas de zero para
toda e qualquer separação de intervalo de tempo. Se a série temporal não for aleatória, uma ou mais das autocorrelações serão significativamente
diferentes de zero. As linhas horizontais exibidas no gráfico correspondem às faixas de confiança de 95% e 99%. A linha tracejada representa a faixa
de confiança de 99%. Consulte a entrada da Wikipedia para obter mais informações sobre gráficos de autocorrelação.
Em [110]: plt.figure();
Em [113]: autocorrelation_plot(dados);
Gráfico de inicialização
Os gráficos de bootstrap são usados para avaliar visualmente a incerteza de uma estatística, como média, mediana, intervalo médio, etc. Um
subconjunto aleatório de um tamanho especificado é selecionado de um conjunto de dados, a estatística em questão é calculada para este
subconjunto e o processo é repetido um determinado número de vezes. Os gráficos e histogramas resultantes são o que constitui o gráfico de bootstrap.
RadViz
RadViz é uma forma de visualizar dados multivariados. É baseado em um algoritmo simples de minimização da tensão da mola.
Basicamente você configura vários pontos em um avião. No nosso caso, eles estão igualmente espaçados em um círculo unitário. Cada
ponto representa um único atributo. Você então finge que cada amostra no conjunto de dados está presa a cada um desses pontos por
uma mola, cuja rigidez é proporcional ao valor numérico desse atributo (eles são normalizados para intervalo unitário).
O ponto no plano onde a nossa amostra se estabelece (onde as forças que atuam na nossa amostra estão em equilíbrio) é onde um
ponto representando a nossa amostra será desenhado. Dependendo da classe a que a amostra pertence, ela terá cores diferentes.
Consulte o pacote R Radviz para obter mais informações.
Em [119]: plt.figure();
A partir da versão 1.5 e superior, o matplotlib oferece uma variedade de estilos de plotagem pré-configurados. A configuração do estilo
pode ser usada para dar facilmente aos gráficos a aparência geral desejada. Definir o estilo é tão fácil quanto chamar matplotlib.style.
use(my_plot_style) antes de criar seu gráfico. Por exemplo, você poderia escrever matplotlib.style.use('ggplot') para gráficos no estilo
ggplot.
Você pode ver os vários nomes de estilos disponíveis em matplotlib.style.available e é muito fácil experimentá-los.
A maioria dos métodos de plotagem possui um conjunto de argumentos de palavras-chave que controlam o layout e a formatação do gráfico retornado:
Em [121]: plt.figure();
Para cada tipo de gráfico (por exemplo, linha, barra, dispersão) quaisquer palavras-chave de argumentos adicionais são
passadas para a função matplotlib correspondente (ax.plot(), ax.bar(), ax.scatter()). Eles podem ser usados para controlar estilos
adicionais, além do que o pandas oferece.
Controlando a lenda
Você pode definir o argumento da legenda como False para ocultar a legenda, que é mostrada por padrão.
Em [124]: df = df.cumsum()
Em [125]: df.plot(legend=False);
Controlando os rótulos
Você pode definir os argumentos xlabel e ylabel para fornecer rótulos personalizados ao gráfico para os eixos x e y. Por padrão, o
pandas escolherá o nome do índice como xlabel, deixando-o vazio para ylabel.
Em [126]: df.plot();
Balanças
Em [129]: ts = np.exp(ts.cumsum())
Em [130]: ts.plot(logy=True);
Em [131]: df["A"].plot();
Para plotar algumas colunas em um DataFrame, forneça os nomes das colunas à palavra-chave secundário_y:
Em [133]: plt.figure();
Observe que as colunas plotadas no eixo y secundário são automaticamente marcadas com “(direita)” na legenda. Para desativar a
marcação automática, use a palavra-chave mark_right=False:
Em [137]: plt.figure();
pandas fornece formatadores personalizados para gráficos de séries temporais. Eles alteram a formatação dos rótulos dos eixos
para datas e horas. Por padrão, os formatadores personalizados são aplicados apenas a gráficos criados por pandas com
DataFrame. plot() ou Series.plot(). Para que sejam aplicados a todos os gráficos, incluindo aqueles feitos pelo matplotlib, defina a
opção pd.options.plotting.matplotlib.register_converters = True ou use pandas.plotting. registrar_matplotlib_converters().
pandas inclui ajuste automático de resolução de ticks para dados de séries temporais de frequência regular. Para casos limitados em que os
pandas não podem inferir as informações de frequência (por exemplo, em um twinx criado externamente), você pode optar por suprimir esse
comportamento para fins de alinhamento.
Em [139]: plt.figure();
Em [140]: df["A"].plot();
Em [141]: plt.figure();
Em [142]: df["A"].plot(x_compat=True);
Se você tiver mais de um gráfico que precisa ser suprimido, o método use em pandas.plotting.plot_params pode
ser usado em uma instrução with:
Em [143]: plt.figure();
TimedeltaIndex agora usa os métodos nativos de localização de ticks do matplotlib. É útil chamar o ajuste automático de ticks de data
do matplotlib para figuras cujos rótulos de ticks se sobrepõem.
Subtramas
Cada série em um DataFrame pode ser plotada em um eixo diferente com a palavra-chave subplots:
O layout das subparcelas pode ser especificado pela palavra-chave layout. Pode aceitar (linhas, colunas). A palavra-chave layout
também pode ser usada em hist e boxplot. Se a entrada for inválida, um ValueError será gerado.
O número de eixos que podem ser contidos por linhas x colunas especificadas pelo layout deve ser maior que o número de subparcelas
necessárias. Se o layout puder conter mais eixos do que o necessário, os eixos em branco não serão desenhados. Semelhante ao método de
remodelação de um array NumPy, você pode usar -1 para uma dimensão para calcular automaticamente o número de linhas ou colunas
necessárias, considerando a outra.
O número necessário de colunas (3) é inferido do número de séries a serem plotadas e do número fornecido de linhas (2).
Você pode passar vários eixos criados anteriormente como uma lista por meio da palavra-chave ax. Isso permite layouts mais complicados. Os eixos
passados devem ter o mesmo número das subparcelas que estão sendo desenhadas.
Quando vários eixos são passados por meio da palavra-chave ax, as palavras-chave layout, sharex e sharey não afetam a saída.
Você deve passar explicitamente sharex=False e sharey=False, caso contrário você verá um aviso.
Outra opção é passar um argumento ax para Series.plot() para plotar em um eixo específico:
Barras de erro horizontais e verticais podem ser fornecidas aos argumentos das palavras-chave xerr e yerr para plot(). Os valores
de erro podem ser especificados usando vários formatos:
• Como um DataFrame ou ditado de erros com nomes de colunas correspondentes ao atributo de colunas da plotagem
DataFrame ou correspondente ao atributo name da Série.
• Como uma str indicando quais das colunas do DataFrame plotado contém os valores de erro.
• Como valores brutos (lista, tupla ou np.ndarray). Deve ter o mesmo comprimento do DataFrame/Series de plotagem.
Aqui está um exemplo de uma maneira de representar facilmente as médias do grupo com desvios padrão dos dados brutos.
# Gere os dados
Em [164]: ix3 = pd.MultiIndex.from_arrays(
.....: [
.....: ["a", "a ", "a", "a", "a", "b ", "b", "b", "b", "b"],
.....: ["foo", "foo", "foo", "bar", "bar", "foo", "foo", "bar", "bar", "bar"],
.....: ],
.....: nomes=["letra", "palavra"],
..... :)
.....:
Em [169]: significa
Fora[169]:
dados1 dados2
palavra letra
a barra 3,500000 6,000000
foo 4.666667 6.666667
b barra 3,666667 4,000000
foo 3,000000 4,500000
Em [170]: erros
Fora[170]:
dados1 dados2
palavra letra
a barra 0,707107 1,414214
foo 3.785939 2.081666
b barra 2,081666 2,645751
foo 1,414214 0,707107
# Trama
Em [171]: fig, ax = plt.subplots()
Barras de erro assimétricas também são suportadas, porém valores brutos de erro devem ser fornecidos neste caso. Para uma série de
comprimento N, uma matriz 2xN deve ser fornecida indicando erros inferiores e superiores (ou esquerdo e direito). Para um DataFrame
MxN, os erros assimétricos devem estar em uma matriz Mx2xN.
Aqui está um exemplo de uma maneira de traçar o intervalo mínimo/máximo usando barras de erro assimétricas.
# erros devem ser positivos e definidos na ordem inferior e superior In [175]: erros = [[means[c] -
mins[c], maxs[c] - mean[c]] for c in df3.columns ]
# Plotar
em [176]: fig, ax = plt.subplots()
Plotando tabelas
A plotagem com tabela matplotlib agora é suportada em DataFrame.plot() e Series.plot() com uma palavra-chave de tabela. A palavra-
chave table pode aceitar bool, DataFrame ou Series. A maneira simples de desenhar uma tabela é especificar table=True. Os dados
serão transpostos para atender ao layout padrão do matplotlib.
Além disso, você pode passar um DataFrame ou Série diferente para a palavra-chave table. Os dados serão desenhados conforme exibidos
no método de impressão (não transpostos automaticamente). Se necessário, deve ser transposto manualmente conforme mostrado no
exemplo abaixo.
Também existe uma função auxiliar pandas.plotting.table, que cria uma tabela de DataFrame ou Series e a adiciona a uma instância
matplotlib.Axes. Esta função pode aceitar palavras-chave que a tabela matplotlib possui.
Nota: Você pode obter instâncias de tabela nos eixos usando a propriedade axes.tables para decorações adicionais. Consulte a documentação da tabela
matplotlib para obter mais informações.
Mapas de cores
Um possível problema ao plotar um grande número de colunas é que pode ser difícil distinguir algumas séries devido à repetição das
cores padrão. Para remediar isso, a plotagem DataFrame suporta o uso do argumento colormap, que aceita um mapa de cores Matplotlib
ou uma string que é o nome de um mapa de cores registrado no Matplotlib. Uma visualização dos mapas de cores matplotlib padrão
está disponível aqui.
Como matplotlib não oferece suporte direto a mapas de cores para gráficos baseados em linhas, as cores são selecionadas com base
em um espaçamento uniforme determinado pelo número de colunas no DataFrame. Não há consideração pela cor de fundo; portanto,
alguns mapas de cores produzirão linhas que não são facilmente visíveis.
Em [190]: df = df.cumsum()
Em [191]: plt.figure();
Em [192]: df.plot(colormap="cubehelix");
Em [194]: plt.figure();
Em [195]: df.plot(colormap=cm.cubehelix);
Os mapas de cores também podem ser usados em outros tipos de gráficos, como gráficos de barras:
Em [197]: dd = dd.cumsum()
Em [198]: plt.figure();
Em [199]: dd.plot.bar(colormap="Verdes");
Em [200]: plt.figure();
Em [202]: plt.figure();
Em algumas situações ainda pode ser preferível ou necessário preparar gráficos diretamente com matplotlib, por exemplo quando um
certo tipo de gráfico ou personalização (ainda) não é suportado pelo pandas. Os objetos Series e DataFrame se comportam como
arrays e podem, portanto, ser passados diretamente para funções matplotlib sem conversões explícitas.
O pandas também registra automaticamente formatadores e localizadores que reconhecem índices de data, estendendo assim o
suporte de data e hora a praticamente todos os tipos de gráficos disponíveis no matplotlib. Embora essa formatação não forneça o
mesmo nível de refinamento que você obteria ao plotar via pandas, ela pode ser mais rápida ao plotar um grande número de pontos.
Em [204]: preço =
.....: pd.Series( np.random.randn(150).cumsum(),
.....: index=pd.date_range("2000-1-1", períodos=150, freq="B"),
..... :)
.....:
Em [205]: ma = price.rolling(20).mean()
Em [207]: plt.figure();
A partir da versão 0.25, os pandas podem ser estendidos com backends de plotagem de terceiros. A ideia principal é permitir que os
usuários selecionem um backend de plotagem diferente daquele fornecido com base no Matplotlib.
Isso pode ser feito passando 'backend.module' como o argumento backend na função plot. Por exemplo:
Alternativamente, você também pode definir esta opção globalmente, não é necessário especificar a palavra-chave em cada chamada de gráfico.
Por exemplo:
Ou:
O módulo backend pode então usar outras ferramentas de visualização (Bokeh, Altair, hvplot,...) para gerar os gráficos. Algumas bibliotecas
que implementam um backend para pandas estão listadas na página ecossistema ecossistema.visualization.
Esta seção demonstra a visualização de dados tabulares usando a classe Styler . Para obter informações sobre visualização com gráficos,
consulte Visualização de gráficos. Este documento foi escrito como um Jupyter Notebook e pode ser visualizado ou baixado aqui.
O estilo deve ser executado após o processamento dos dados em um DataFrame. O Styler cria uma <table> HTML e aproveita a linguagem
de estilo CSS para manipular muitos parâmetros, incluindo cores, fontes, bordas, plano de fundo, etc.
Veja aqui mais informações sobre como estilizar tabelas HTML. Isso permite muita flexibilidade imediata e até permite que os desenvolvedores
da Web integrem DataFrames em seus designs de interface de usuário existentes.
O atributo DataFrame.style é uma propriedade que retorna um objeto Styler . Ele possui um método _repr_html_ definido para que sejam
renderizados automaticamente no Jupyter Notebook.
A saída acima é muito semelhante à representação HTML padrão do DataFrame. Mas o HTML aqui já anexou algumas classes CSS a cada
célula, mesmo que ainda não tenhamos criado nenhum estilo. Podemos visualizá-los chamando o método .to_html() , que retorna o HTML
bruto como string, o que é útil para processamento posterior ou adição a um arquivo - leia mais sobre CSS e HTML. A seguir mostraremos
como podemos usá-los para formatar o DataFrame para ser mais comunicativo. Por exemplo, como podemos construir s:
[4]: s
Formatando Valores
Antes de adicionar estilos, é útil mostrar que o Styler pode distinguir o valor de exibição do valor real , tanto nos valores de dados
quanto nos cabeçalhos de índices ou colunas. Para controlar o valor de exibição, o texto é impresso em cada célula como string, e
podemos usar os métodos .format() e .format_index() para manipular isso de acordo com uma string de especificação de formato ou
um callable que recebe um único valor e retorna uma linha. É possível definir isso para toda a tabela, ou índice, ou para colunas
individuais, ou níveis MultiIndex.
Além disso, a função format tem um argumento de precisão para ajudar especificamente na formatação de carros flutuantes,
bem como separadores decimais e de milhares para suportar outras localidades, um argumento na_rep para exibir dados
ausentes e um argumento de escape para ajudar a exibir HTML seguro ou LaTeX seguro. O formatador padrão está configurado
para adotar o styler.format do pandas. opção de precisão, controlável usando pd.option_context('format.precision', 2):
Usar o Styler para manipular a exibição é um recurso útil porque manter a indexação e os valores dos dados para outros fins
proporciona maior controle. Você não precisa sobrescrever seu DataFrame para exibi-lo como desejar. Aqui está um exemplo
de uso das funções de formatação enquanto ainda depende dos dados subjacentes para indexação e cálculos.
def condição_de_chuva(v): se
v < 1,75:
retornar elif
"seco" v < 2,75:
retornar "Chuva"
retornar "Chuva Forte"
def make_pretty(styler):
styler.set_caption(" Condições climáticas")
styler.format(rain_condition)
styler.format_index(lambda v: v.strftime("%A"))
styler.background_gradient(axis=None, vmin=1, vmax=5, cmap="YlGnBu") modelador de
retorno
clima_df
[7]: weather_df.loc["2021-01-04":"2021-01-08"].style.pipe(make_pretty)
Ocultando dados
Os cabeçalhos do índice e das colunas podem ser completamente ocultos, bem como subselecionar linhas ou colunas que se deseja excluir.
Ambas as opções são executadas usando os mesmos métodos.
O índice pode ser ocultado da renderização chamando .hide() sem nenhum argumento, o que pode ser útil se o seu índice for baseado em
números inteiros. Da mesma forma, os cabeçalhos das colunas podem ser ocultados chamando .hide(axis=“columns”) sem quaisquer
argumentos adicionais.
Linhas ou colunas específicas podem ser ocultadas da renderização chamando o mesmo método .hide() e passando um rótulo de linha/
coluna, um tipo de lista ou uma fatia de rótulos de linha/coluna para o argumento do subconjunto.
Ocultar não altera a disposição inteira das classes CSS, por exemplo, ocultar as duas primeiras colunas de um DataFrame significa que a
indexação da classe de coluna ainda começará em col2, já que col0 e col1 são simplesmente ignorados.
Podemos atualizar nosso objeto Styler anterior para ocultar alguns dados e formatar os valores.
• Usando .set_table_styles() para controlar áreas mais amplas da tabela com CSS interno especificado. Embora os estilos de tabela permitam
flexibilidade para adicionar seletores e propriedades CSS que controlam todas as partes individuais da tabela, eles são difíceis de manejar
para especificações de células individuais. Além disso, observe que os estilos de tabela não podem ser exportados para Excel.
• Usar .set_td_classes() para vincular diretamente classes CSS externas às suas células de dados ou vincular as classes CSS internas
criadas por .set_table_styles(). Veja aqui. Eles não podem ser usados em linhas ou índices de cabeçalho de coluna e também não
serão exportados para Excel.
• Usando as funções .apply() e .applymap() para adicionar CSS interno direto a células de dados específicas. Veja aqui. A partir da
versão 1.4.0 também existem métodos que funcionam diretamente nas linhas ou índices do cabeçalho da coluna; .apply_index()
e .ap-plymap_index(). Observe que apenas esses métodos adicionam estilos que serão exportados para Excel. Esses métodos
funcionam de maneira semelhante a DataFrame.apply() e DataFrame.applymap().
Os estilos de tabela são flexíveis o suficiente para controlar todas as partes individuais da tabela, incluindo cabeçalhos de colunas e índices. No
entanto, eles podem ser difíceis de digitar para células de dados individuais ou para qualquer tipo de formatação condicional, por isso recomendamos
que os estilos de tabela sejam usados para estilos amplos, como linhas ou colunas inteiras de uma vez.
Os estilos de tabela também são usados para controlar recursos que podem ser aplicados a toda a tabela de uma vez, como a criação de uma
funcionalidade genérica de foco. O pseudo-seletor :hover, assim como outros pseudo-seletores, só podem ser usados desta forma.
Para replicar o formato normal de seletores e propriedades CSS (pares de valores de atributos), por exemplo
tr:hover { cor
de fundo: #ffff99;
}
o formato necessário para passar estilos para .set_table_styles() é uma lista de dictos, cada um com uma tag seletora de CSS e
propriedades CSS. As propriedades podem ser uma lista de 2 tuplas ou uma string CSS regular, por exemplo:
[10]: cell_hover = { # para passar o mouse sobre a linha use <tr> em vez de <td>
'selector': 'td:hover', 'props':
[('background-color', '#ffffb3')]
} index_names =
{ 'seletor': '.index_name', 'props':
'estilo de fonte: itálico; cor: cinza escuro; peso da fonte:normal;'
} cabeçalhos = {
'seletor': 'th:not(.index_name)', 'props': 'cor de
fundo: #000066; cor branca;'
Em seguida, apenas adicionamos mais alguns artefatos de estilo direcionados a partes específicas da tabela. Tenha cuidado aqui, já que
estamos encadeando métodos , precisamos instruir explicitamente o método a não sobrescrever os estilos existentes.
Como método de conveniência (desde a versão 1.2.0), também podemos passar um ditado para .set_table_styles() que contém chaves
de linha ou coluna. Nos bastidores, o Styler apenas indexa as chaves e adiciona classes .col<m> ou .row<n> relevantes conforme
necessário aos seletores CSS fornecidos.
[14]: s.set_table_styles({
('Regressão', 'Tumor'): [{'selector': 'th', 'props': 'border-left: 1px branco sólido ÿÿ'},
Se você projetou um site, é provável que já tenha um arquivo CSS externo que controla o estilo de tabelas e objetos de células
dentro dele. Você pode querer usar esses arquivos nativos em vez de duplicar todo o CSS em python (e duplicar qualquer trabalho
de manutenção).
Atributos da tabela
É muito fácil adicionar uma classe à <table> principal usando .set_table_attributes(). Este método também pode anexar estilos
embutidos - leia mais em Hierarquias CSS.
O método .set_td_classes() aceita um DataFrame com índices e colunas correspondentes ao DataFrame do Styler subjacente . Esse
DataFrame conterá strings como classes css para adicionar a células de dados individuais: os elementos <td> da <table>. Em vez
de usar CSS externo, criaremos nossas classes internamente e as adicionaremos ao estilo da tabela. Salvaremos a adição de bordas
até a seção de dicas de ferramentas.
s.set_td_classes(cell_color)
Usamos os seguintes métodos para passar suas funções de estilo. Ambos os métodos pegam uma função (e alguns outros argumentos
de palavras-chave) e aplicam-na ao DataFrame de uma determinada maneira, renderizando estilos CSS.
• .applymap() (elementwise): aceita uma função que recebe um único valor e retorna uma string com o atributo CSS-
par de valores.
• .apply() (coluna/linha/tabela): aceita uma função que pega uma Série ou DataFrame e retorna uma Série, DataFrame ou matriz
numpy com uma forma idêntica, onde cada elemento é uma string com um atributo CSS par de valores. Este método passa cada
coluna ou linha do seu DataFrame, uma de cada vez, ou a tabela inteira de uma vez, dependendo do argumento da palavra-
chave do eixo. Para coluna use axis=0, rowwise use axis=1, e para toda a tabela de uma vez use axis=None.
Este método é poderoso para aplicar lógica múltipla e complexa a células de dados. Criamos um novo DataFrame para demonstrar isso.
Por exemplo, podemos construir uma função que colore o texto se for negativo e encadear isso com uma função que esmaece
parcialmente células de valor insignificante. Como isso analisa cada elemento, usamos applymap.
Também podemos construir uma função que destaque o valor máximo em linhas, colunas e DataFrame de uma só vez. Neste caso
usamos aplicar. Abaixo destacamos o máximo em uma coluna.
Podemos usar a mesma função nos diferentes eixos, destacando aqui o máximo do DataFrame em roxo e os máximos das linhas em
rosa.
Este último exemplo mostra como alguns estilos foram substituídos por outros. Em geral o estilo aplicado mais recentemente está ativo,
mas você pode ler mais na seção sobre hierarquias CSS. Você também pode aplicar esses estilos a partes mais granulares do
DataFrame - leia mais na seção sobre fatiamento de subconjuntos.
É possível replicar algumas dessas funcionalidades usando apenas classes, mas pode ser mais complicado. Veja item 3) de Otimização
Dica de depuração: se você estiver tendo problemas para escrever sua função de estilo, tente simplesmente passá-la para
DataFrame.apply. Internamente, Styler.apply usa DataFrame.apply então o resultado deve ser o mesmo, e com DataFrame.apply
você poderá inspecionar a saída da string CSS da função pretendida em cada célula.
• .applymap_index() (elementwise): aceita uma função que recebe um único valor e retorna uma string com o CSS
par atributo-valor.
• .apply_index() (nível): aceita uma função que pega uma Série e retorna uma Série, ou array numpy com formato idêntico onde
cada elemento é uma string com um par atributo-valor CSS. Este método passa cada nível do seu índice, um de cada vez.
Para estilizar o índice use axis=0 e para estilizar os cabeçalhos das colunas use axis=1.
Você pode selecionar um nível de MultiIndex, mas atualmente nenhum aplicativo de subconjunto semelhante está disponível para esses métodos.
As legendas da tabela podem ser adicionadas com o método .set_caption() . Você pode usar estilos de tabela para controlar o CSS relevante para
a legenda.
Adicionar dicas de ferramentas (desde a versão 1.3.0) pode ser feito usando o método .set_tooltips() da mesma forma que você pode
adicionar classes CSS a células de dados, fornecendo um DataFrame baseado em string com índices e colunas que se cruzam. Você não
precisa especificar um nome css_class ou qualquer adereço css para as dicas de ferramentas, pois existem padrões padrão, mas a opção
existe se você quiser mais controle visual.
[29]: tt = pd.DataFrame([['Este modelo tem uma taxa de verdadeiros positivos muito forte', "O número total de
falsos negativos deste modelo é muito alto"]],
index=['Tumor (Positivo)'], colunas=df.columns[[0,3]])
s.set_tooltips(tt, props='visibilidade: oculto; posição: absoluto; índice z: 1; borda:ÿ ÿÿ1px sólido #000066;'
'cor de fundo: branco; cor: #000066; tamanho da fonte: 0,8em;' 'transformar: traduzir(0px,
-24px); preenchimento: 0,6em; fronteira-
ÿÿraio: 0,5em;')
A única coisa que falta fazer em nossa tabela é adicionar bordas de destaque para chamar a atenção do público para as dicas de ferramentas.
Criaremos classes CSS internas como antes, usando estilos de tabela. Definir classes sempre sobrescreve, então precisamos ter
certeza de adicionar as classes anteriores.
Os exemplos que mostramos até agora para as funções Styler.apply e Styler.applymap não demonstraram o uso do argumento subset.
Este é um argumento útil que permite muita flexibilidade: permite aplicar estilos a linhas ou colunas específicas, sem ter que codificar essa
lógica em sua função de estilo.
• Uma lista (ou matriz de série ou NumPy) é tratada como vários rótulos de coluna
Considere usar pd.IndexSlice para construir a tupla do último. Criaremos um DataFrame MultiIndexed para demonstrar a funcionalidade.
df3
Usaremos subconjunto para destacar o máximo na terceira e quarta colunas com texto em vermelho. Destacaremos a região fatiada
do subconjunto em amarelo.
Se combinado com o IndexSlice conforme sugerido, ele poderá indexar ambas as dimensões com maior flexibilidade.
Isso também fornece flexibilidade para subselecionar linhas quando usado com o eixo = 1.
Suponha que queiramos destacar o máximo nas colunas 2 e 4 apenas no caso de a soma das colunas 1 e 3 ser menor que -2,0
(essencialmente excluindo as linhas (:,'r2')).
Somente o fatiamento baseado em rótulo é suportado no momento, não posicional e não chamável.
Se sua função de estilo usa um argumento de palavra-chave de subconjunto ou eixo, considere agrupar sua função em um arquivo
functools. parcial, parcializando essa palavra-chave.
2.16.9 Otimização
Geralmente, para tabelas menores e na maioria dos casos, o HTML renderizado não precisa ser otimizado e não recomendamos isso.
Existem dois casos em que vale a pena considerar:
• Se você estiver renderizando e estilizando uma tabela HTML muito grande, alguns navegadores terão problemas de desempenho.
• Se você estiver usando o Styler para criar dinamicamente parte de interfaces de usuário on-line e quiser melhorar o desempenho da rede
desempenho.
Ignore o uuid e defina cell_ids como False. Isso evitará HTML desnecessário.
Isto é melhor:
Use estilos de tabela sempre que possível (por exemplo, para todas as células, linhas ou colunas de cada vez), pois o CSS é quase sempre
mais eficiente que outros formatos.
[40]: adereços = 'família de fontes: "Times New Roman", Times, serif; cor: #e83e8c; tamanho da fonte: 1,3em;'
df4.style.applymap(lambda x: adereços, subconjunto=[1])
Isto é melhor:
Para DataFrames grandes onde o mesmo estilo é aplicado a muitas células, pode ser mais eficiente declarar os estilos como
classes e depois aplicar essas classes às células de dados, em vez de aplicar estilos diretamente às células. No entanto,
provavelmente ainda é mais fácil usar a API da função Styler quando você não está preocupado com a otimização.
Isto é melhor:
df2.style.set_table_styles([
{'seletor': '.cls-1', 'props': 'cor:branco;cor de fundo:azul escuro;'}, {'seletor': '.cls-2', 'props': 'cor:branco ;cor de
fundo: rosa;'}, {'selector': '.cls-3', 'props': 'cor: branco; cor de fundo: roxo;'}
As dicas de ferramentas exigem que cell_ids funcionem e geram elementos HTML extras para cada célula de dados.
Você pode remover HTML desnecessário ou encurtar os nomes de classe padrão substituindo o ditado CSS padrão. Você pode ler
um pouco mais sobre CSS abaixo.
[44]: meu_css = {
"row_heading": "",
"col_heading": "",
"index_name": "", "col":
"c", "row": "r",
"col_trim": "",
"row_trim": "" , "nível":
"l", "dados": "", "em
branco": "",
imprimir(html.to_html())
}
#T_ .c1 { cor:
verde;
}
#T_ .l0 { cor:
azul;
} </style>
<table id="T_">
<thead>
(continua na próxima página)
<tr>
<th class=" l0 r0" >0</th> <td class="
r0 c0" >1</td> <td class=" r0 c1" >2</
td> </tr>
<tr>
<th class=" l0 r1" >1</th> <td class="
r1 c0" >3</td> <td class=" r1 c1" >4</
td> </tr> </tbody> </tabela>
[45]: html
Algumas funções de estilo são tão comuns que nós as “incorporamos” ao Styler, então você não precisa escrevê-las e aplicá-las
você mesmo. A lista atual de tais funções é:
• .background_gradient: um método flexível para destacar células com base em seus ou outros valores em uma escala numérica.
• .text_gradient: método semelhante para destacar texto com base em seus ou outros valores em uma escala numérica.
A documentação individual de cada função geralmente fornece mais exemplos de seus argumentos.
Destacar Nulo
Destacar entre
Este método aceita intervalos como float ou matrizes NumPy ou séries, desde que os índices correspondam.
Destacar Quantil
Você pode criar “mapas de calor” com os métodos background_gradient e text_gradient. Eles requerem matplotlib, e usaremos
Seaborn para obter um bom mapa de cores.
df2.style.background_gradient(cmap=cm)
[51]: df2.style.text_gradient(cmap=cm)
.background_gradient e .text_gradient possuem vários argumentos de palavras-chave para personalizar os gradientes e cores.
Veja a documentação.
Definir propriedades
Use Styler.set_properties quando o estilo não depender realmente dos valores. Este é apenas um wrapper simples para .applymap
onde a função retorna as mesmas propriedades para todas as células.
Gráficos de barra
Argumentos de palavras-chave adicionais fornecem mais controle sobre centralização e posicionamento, e você pode passar uma
lista de [color_negative, color_positivo] para destacar valores mais baixos e mais altos ou um mapa de cores matplotlib.
Para mostrar um exemplo, veja como você pode alterar o acima com a nova opção de alinhamento, combinada com a configuração
dos limites vmin e vmax, a largura da figura e os adereços css subjacentes das células, deixando espaço para exibir o texto e as
barras. Também usamos text_gradient para colorir o texto da mesma forma que as barras usando um mapa de cores matplotlib
(embora neste caso a visualização seja provavelmente melhor sem este efeito adicional).
O exemplo a seguir visa dar um destaque ao comportamento das novas opções de alinhamento:
Digamos que você tenha um estilo adorável criado para um DataFrame e agora queira aplicar o mesmo estilo a um segundo DataFrame.
Exporte o estilo com df1.style.export e importe-o no segundo DataFrame com df1.style.set
[57]: style1 =
df2.style\ .applymap(style_negative, props='color:red;')\ .applymap(lambda v:
'opacity: 20%;' if (v < 0,3) e (v > -0,3 ) else Nenhum)\ .set_table_styles([{"selector": "th", "props": "color:
blue;"}])\ .hide(axis="index")
estilo1
Observe que você pode compartilhar os estilos mesmo que eles reconheçam os dados. Os estilos são reavaliados no novo
DataFrame em que foram usados.
2.16.12 Limitações
• O índice e as colunas não precisam ser exclusivos, mas determinadas funções de estilo só podem funcionar com índices exclusivos.
• Não há grande repr e o desempenho da construção não é ótimo; embora tenhamos algumas otimizações de HTML
• Você só pode aplicar estilos, não pode inserir novas entidades HTML, exceto através de subclasses.
Widgets
O Styler interage muito bem com widgets. Se você estiver visualizando isso on-line em vez de executar o notebook sozinho, estará
perdendo o ajuste interativo da paleta de cores.
Ampliar
dict(selector="tr:hover td:hover",
adereços=[('largura máxima', '200px'),
('tamanho da fonte', '12pt')])
]
bigdf.style.background_gradient(cmap,
axis=1)\ .set_properties(**{'max-width': '80px', 'font-size': '1pt'})\ .set_caption("Passe o
mouse para ampliar")
\ .format(precisão=2)\ .set_table_styles(magnificar())
Cabeçalhos fixos
Se você exibir uma matriz grande ou DataFrame em um notebook, mas quiser sempre ver os cabeçalhos das colunas e
linhas, poderá usar o método .set_sticky que manipula os estilos de tabela CSS.
Escape de HTML
Suponha que você precise exibir HTML dentro de HTML, o que pode ser um pouco complicado quando o renderizador não consegue distinguir.
Você pode usar a opção de formatação de escape para lidar com isso e até mesmo usá-la em um formatador que contenha o próprio HTML.
[65]: df4.style.format(escape="html")
Algum suporte (desde a versão 0.20.0) está disponível para exportar DataFrames estilizados para planilhas do Excel usando os
mecanismos OpenPyXL ou XlsxWriter. As propriedades CSS2.2 tratadas incluem:
• cor de fundo
• cor
• família de fontes
• estilo de fonte
• espessura da fonte
• alinhamento de texto
• decoração de texto
• alinhamento vertical
• Atualmente quebrado: estilo de borda, largura de borda, cor de borda e suas {variáveis superior, direita, inferior, esquerda
formigas}
• Somente cores nomeadas CSS2 e cores hexadecimais no formato #rgb ou #rrggbb são atualmente suportadas.
• As seguintes propriedades pseudo CSS também estão disponíveis para definir propriedades de estilo específicas do Excel:
– formato numérico
Estilos de nível de tabela e classes CSS de células de dados não estão incluídos na exportação para Excel: células individuais devem
ter suas propriedades mapeadas pelos métodos Styler.apply e/ou Styler.applymap.
[67]: df2.style.\
applymap(style_negative, props='color:red;').\ destaque_max(axis=0).
\ to_excel('styled.xlsx',
engine='openpyxl')
Existe suporte (desde a versão 1.3.0) para exportar Styler para LaTeX. A documentação do método .to_latex fornece mais detalhes e
vários exemplos.
A linguagem Cascading Style Sheet (CSS), projetada para influenciar como um navegador renderiza elementos HTML, tem suas
próprias peculiaridades. Ele nunca relata erros: apenas os ignora silenciosamente e não renderiza seus objetos como você deseja, o
que às vezes pode ser frustrante. Aqui está uma breve introdução sobre como o Styler cria HTML e interage com CSS, com conselhos
sobre armadilhas comuns a serem evitadas.
• Células com nomes de índice e coluna incluem index_name e level<k> onde k é seu nível em um MultiIndex
– cabeçalho_da_linha
– col_heading
– dados
A estrutura do id é T_uuid_level<k>_row<m>_col<n> onde level<k> é usado apenas em títulos, e os cabeçalhos terão apenas
row<m> ou col<n> o que for necessário. Por padrão, também acrescentamos cada identificador de linha/coluna com um UUID
exclusivo para cada DataFrame para que o estilo de um não colida com o estilo de outro dentro do mesmo bloco de notas ou página.
Você pode ler mais sobre o uso de UUIDs na Otimização.
<tr>
(continua na próxima página)
<tr>
<th id="T_208c9_level0_row0" class="row_heading level0 row0" >i1</th> <td id="T_208c9_row0_col0"
class="dados row0 col0" >1</td> <td id="T_208c9_row0_col1" class=" dados linha0 col1"
>2</td> </tr>
<tr>
<th id="T_208c9_level0_row1" class="row_heading level0 row1" >i2</th> <td id="T_208c9_row1_col0"
class="dados row1 col0" >3</td> <td id="T_208c9_row1_col1" class=" dados linha1 col1"
>4</td> </tr> </tbody> </table>
Hierarquias CSS
Os exemplos mostraram que quando os estilos CSS se sobrepõem, aquele que vem por último na renderização HTML tem precedência.
Portanto, o seguinte produz resultados diferentes:
Isso só é verdade para regras CSS equivalentes em hierarquia ou importância. Você pode ler mais sobre a especificidade do CSS aqui ,
mas para nossos propósitos é suficiente resumir os pontos principais:
Uma pontuação de importância CSS para cada elemento HTML é derivada começando em zero e adicionando:
[71]: df4.style.set_uuid('a_')
\ .set_table_styles([{'selector': 'td', 'props': 'color:red;'}])\ .applymap(lambda x: 'color :verde;')
Este texto é vermelho porque o seletor gerado #T_a_ td vale 101 (ID mais elemento), enquanto #T_a_row0_col0 vale apenas 100 (ID),
portanto é considerado inferior mesmo que no HTML venha depois do anterior.
[72]: df4.style.set_uuid('b_')
\ .set_table_styles([{'selector': 'td', 'props': 'color:red;'}, {'selector': '.cls-1 ', 'adereços': 'cor:azul;'}])
\
.applymap(lambda x: 'cor:verde;')
\ .set_td_classes(pd.DataFrame([['cls-1']]))
No caso acima o texto é azul porque o seletor #T_b_ .cls-1 vale 110 (ID mais classe), que tem precedência.
[73]: df4.style.set_uuid('c_')
\ .set_table_styles([{'selector': 'td', 'props': 'color:red;'}, {'selector': '.cls-1 ', 'props': 'color:blue;'},
{'selector': 'td.data', 'props': 'color:yellow;'}])\ .applymap(lambda x:
'color:green; ')\ .set_td_classes(pd.DataFrame([['cls-1']]))
Agora criamos outro estilo de tabela, desta vez o seletor T_c_td.data (ID mais elemento mais classe) aumenta para 111.
Se o seu estilo não for aplicado e for realmente frustrante, experimente o !important trunfo.
[74]: df4.style.set_uuid('d_')
\ .set_table_styles([{'selector': 'td', 'props': 'color:red;'}, {'selector': '.cls-1 ', 'props': 'color:blue;'},
{'selector': 'td.data', 'props': 'color:yellow;'}])\
2.16.17 Extensibilidade
O núcleo do pandas é, e continuará sendo, suas “estruturas de dados de alto desempenho e fáceis de usar”. Com isso em mente, esperamos
que DataFrame.style atinja dois objetivos
• Fornecer uma API que seja agradável de usar de forma interativa e que seja “boa o suficiente” para muitas tarefas
Se você construir uma ótima biblioteca com base nisso, informe-nos e colocaremos um link para ela.
Subclassificação
Se o modelo padrão não atender às suas necessidades, você pode criar uma subclasse de Styler e estender ou substituir o modelo.
Mostraremos um exemplo de extensão do modelo padrão para inserir um cabeçalho personalizado antes de cada tabela.
Agora que criamos um modelo, precisamos configurar uma subclasse de Styler que o conheça.
) template_html_table = env.get_template("meuhtml.tpl")
Observe que incluímos o carregador original no carregador do nosso ambiente. Isso ocorre porque estendemos o modelo original,
então o ambiente Jinja precisa ser capaz de encontrá-lo.
Agora podemos usar esse estilizador personalizado. É __init__ que leva um DataFrame.
[78]: MeuStyler(df3)
Nosso modelo personalizado aceita uma palavra-chave table_title. Podemos fornecer o valor no método .to_html.
Por conveniência, fornecemos o método Styler.from_custom_template que faz o mesmo que a subclasse personalizada.
Estrutura do modelo
Esta é a estrutura do modelo para o modelo de geração de estilo e para o modelo de geração de tabela:
Modelo de estilo:
[82]: HTML(estilo_estrutura)
Modelo de tabela:
Mudança percentual
Series e DataFrame têm um método pct_change() para calcular a variação percentual em um determinado número de períodos
(usando fill_method para preencher valores NA/nulos antes de calcular a alteração percentual).
Em [2]: ser.pct_change()
Fora[2]:
0 NaN
1 -1,602976
2 4.334938
3-0,247456
4 -2,067345
5 -1.142903
6 -1,688214
7 -9,759729
tipo d: float64
Em [4]: df.pct_change(períodos=3)
Fora[4]:
0 1 2 3
0 NaN NaN NaN NaN
1 NaN NaN NaN NaN
2 NaN NaN NaN NaN
3 -0,218320 -1,054001 1,987147 -0,510183
4 -0,439121 -1,816454 0,649715 -4,822809
5 -0,127833 -3,042065 -5,866604 -1,776977
(continua na próxima página)
Covariância
Series.cov() pode ser usado para calcular a covariância entre séries (excluindo valores ausentes).
Em [5]: s1 = pd.Series(np.random.randn(1000))
Em [6]: s2 = pd.Series(np.random.randn(1000))
Em [7]: s1.cov(s2)
Saída[7]: 0,0006801088174310875
Analogamente, DataFrame.cov() para calcular covariâncias pareadas entre as séries no DataFrame, excluindo também valores NA/nulos.
Nota: Supondo que os dados faltantes estejam faltando aleatoriamente, isso resulta em uma estimativa para a matriz de covariância
que é imparcial. No entanto, para muitas aplicações esta estimativa pode não ser aceitável porque não é garantido que a matriz de
covariância estimada seja positiva semidefinida. Isto pode levar a correlações estimadas com valores absolutos superiores a um e/ou a
uma matriz de covariância não invertível. Consulte Estimativa de matrizes de covariância para obter mais detalhes.
Em [9]: frame.cov()
Fora[9]:
a b c d e
a 1,000882 -0,003177 -0,002698 -0,006889 0,031912 b -0,003177 1,024721
0,000191 0,009212 0,000857 c -0,002698 0,000191 0,950735 -0 0,031743
-0,005087 d -0,006889 0,009212 -0,031743 1,002983 -0,047952 e 0,031912
0,000857 -0,005087 -0,047952 1,042487
DataFrame.cov também suporta uma palavra-chave opcional min_periods que especifica o número mínimo necessário de observações
para cada par de colunas para ter um resultado válido.
Em [13]: frame.cov()
Fora[13]:
a b c
a 1,123670 -0,412851 0,018169 b -0,412851
1,154141 0,305260 c 0,018169 0,305260
1,301149
(continua na próxima página)
Em [14]: frame.cov(min_periods=12)
Fora[14]:
a b c
um 1,123670 NaN 0,018169
b NaN 1,154141 0,305260
c 0,018169 0,305260 1,301149
Correlação
A correlação pode ser calculada usando o método corr() . Usando o parâmetro método, vários métodos para calcular
correlações são fornecidas:
Todos estes são atualmente calculados usando observações completas aos pares. A Wikipedia tem artigos que cobrem o acima
coeficientes de correlação:
Nota: Consulte as advertências associadas a este método de cálculo de matrizes de correlação na seção de covariância.
Observe que as colunas não numéricas serão automaticamente excluídas do cálculo de correlação.
Em [23]: frame.corr()
Fora[23]:
a b c
a 1,000000 -0,121111 0,069544 b -0,121111
1,000000 0,051742 c 0,069544 0,051742
1,000000
Em [24]: frame.corr(min_periods=12)
Fora[24]:
a c
um 1.000000 bNaN 0,069544
b NaN 1,000000 0,051742
c 0,069544 0,051742 1,000000
O argumento do método também pode ser chamado para um cálculo de correlação genérico. Nesse caso, deve ser uma função
única que produza um único valor a partir de duas entradas ndarray. Suponha que quiséssemos calcular a correlação com base
na interseção do histograma:
Em [26]: frame.corr(method=histogram_intersection)
Fora[26]:
a b c
a 1,000000 -6,404882 -2,058431 b -6,404882
1,000000 -19,255743
c -2,058431 -19,255743 1,000000
Um método relacionado corrwith() é implementado no DataFrame para calcular a correlação entre séries com rótulos semelhantes
contidas em diferentes objetos DataFrame.
Em [31]: df1.corrwith(df2)
Fora[31]:
(continua na próxima página)
um -0,125501
dois -0,493244
três 0,344056
quatro 0,004183
dtype: float64
Classificação de dados
O método rank() produz uma classificação de dados com empates sendo atribuídos à média das classificações (por padrão) para o grupo:
Em [35]: s.rank()
Fora[35]:
a 5,0
b 2,5
c 1,0
d 2,5
e 4,0
tipo d: float64
rank() também é um método DataFrame e pode classificar as linhas (eixo=0) ou as colunas (eixo=1). Os valores NaN são
excluído da classificação.
Em [38]: df
Fora[38]:
0 1 25 3 4
0 -0,904948 -1,163537 -1,457187 0,135463 -1,457187 0,294650
1 -0,976288 -0,244652 -0,748406 -0,999601 -0,748406 -0,800809
2 0,401965 1,460840 1,256057 1,308127 1,256057 0,876004
3 0,205954 0,369552 -0,669304 0,038378 -0,669304 1,140296
4 -0,477586 -0,730705 -1,129149 -0,601463 -1,129149 -0,211196
5 -1,092970 -0,689246 0,908114 0,204848 NaN 0,463347
6 0,376892 0,959292 0,095572 -0,593740 NaN-0,069180
7 -1,002601 1,957794 -0,120708 0,094214 NaN -1,467422
8 -0,547231 0,664402 -0,519424 -0,073254 NaN -1,263544
(continua na próxima página)
Em [39]: df.rank(1)
Fora[39]:
0 1 2 3 4 5
0 4,0 3,0 1,5 5,0 1,5 6,0
1 2,0 6,0 4,5 1,0 4,5 3,0
2 1,0 6,0 3,5 5,0 3,5 2,0
3 4,0 5,0 1,5 3,0 1,5 6,0
4 5,0 3,0 1,5 4,0 1,5 6,0
5 1,0 2,0 5,0 3,0 NaN 4,0 6 4,0 5,0 3,0 1,0 NaN
2,0 7 2,0 5,0 3,0 4,0 NaN 1,0 8 2,0 5,0 3,0 4,0
NaN 1,0 9 2,0 3,0 1,0 4,0 NaN 5,0
rank opcionalmente leva um parâmetro crescente que por padrão é verdadeiro; quando falso, os dados são classificados inversamente, com valores
maiores atribuídos a uma classificação menor.
Funções de janelas
Consulte o guia do usuário de operações de janela para obter uma visão geral das funções de janelamento.
Por “agrupar por” estamos nos referindo a um processo que envolve uma ou mais das seguintes etapas:
Destes, o passo dividido é o mais direto. Na verdade, em muitas situações podemos desejar dividir o conjunto de dados em grupos e fazer
algo com esses grupos. Na etapa de aplicação, podemos desejar fazer o seguinte:
• Agregação: calcule uma estatística resumida (ou estatísticas) para cada grupo. Alguns exemplos:
• Transformação: execute alguns cálculos específicos do grupo e retorne um objeto indexado semelhante. Alguns exemplos:
– Preenchimento de NAs dentro dos grupos com um valor derivado de cada grupo.
• Filtração: descarta alguns grupos, de acordo com um cálculo de grupo que avalia Verdadeiro ou Falso. Alguns
exemplos:
• Alguma combinação dos itens acima: GroupBy examinará os resultados da etapa de aplicação e tentará retornar um resultado sensato
resultado combinado se não se enquadrar em nenhuma das duas categorias acima.
Como o conjunto de métodos de instância de objeto nas estruturas de dados do pandas é geralmente rico e expressivo, muitas vezes simplesmente
deseja invocar, digamos, uma função DataFrame em cada grupo. O nome GroupBy deve ser bastante familiar para quem
usei uma ferramenta baseada em SQL (ou itertools), na qual você pode escrever código como:
Nosso objetivo é tornar operações como essa naturais e fáceis de expressar usando pandas. Abordaremos cada área do GroupBy
funcionalidade, em seguida, forneça alguns exemplos/casos de uso não triviais.
objetos pandas podem ser divididos em qualquer um de seus eixos. A definição abstrata de agrupamento é fornecer um mapeamento de rótulos
para agrupar nomes. Para criar um objeto GroupBy (mais sobre o que é o objeto GroupBy posteriormente), você pode fazer o seguinte:
Em [1]: df = pd.DataFrame(
...: [
...: ("pássaro", "Falconiformes", 389,0),
...: ("pássaro", "Psittaciformes", 24,0),
...: ("mamífero", "Carnívoro", 80,2),
...: ("mamífero", "Primatas", np.nan),
...: ("mamífero", "Carnívoro", 58),
...: ],
...: index=["falcão", "papagaio", "leão", "macaco", "leopardo"],
...: colunas=("classe", "ordem", "max_speed"),
... :)
...:
Em [2]: df
Fora[2]:
ordem de classe max_speed
falcão pássaro Falconiformes 389,0
papagaio pássaro Psittaciformes Carnivora 24,0
leão mamífero Primatas 80,2
macaco mamífero Carnivora NaN
leopardo mamífero 58,0
# padrão é eixo=0
Em [3]: agrupado = df.groupby("class")
• Uma função Python, a ser chamada em cada um dos rótulos dos eixos.
• Para objetos DataFrame, uma string indicando um nome de coluna ou um nome de nível de índice a ser usado para agrupar.
Coletivamente, nos referimos ao agrupamento de objetos como chaves. Por exemplo, considere o seguinte DataFrame:
Nota: Uma string passada para groupby pode referir-se a uma coluna ou a um nível de índice. Se uma string corresponder a uma coluna
nome e um nome de nível de índice, um ValueError será gerado.
Em [6]: df = pd.DataFrame(
...: {
...: "A": ["foo", "bar", "foo", "bar", "foo", "bar", "foo", "foo"],
...: "B": ["um", "um", "dois", "três", "dois", "dois", "um", "três"],
...: "C": np.random.randn(8),
...: "D": np.random.randn(8),
...: }
... :)
...:
Em [7]: df
Fora[7]:
A B C D
0 foo 1 um 0,469112 -0,861849
compasso um -0,282863 -2,104569
2 foo 3 dois -1,509059 -0,494929
compasso três -1,135632 1,071804
4 foo 5 dois 1,212112 0,721555
compasso dois -0,173215 -0,706771
6 foo 7 um 0,119209 -1,039575
foo três -1,044236 0,271860
Em um DataFrame, obtemos um objeto GroupBy chamando groupby(). Poderíamos naturalmente agrupar por A ou B
colunas ou ambas:
Se também tivermos um MultiIndex nas colunas A e B, podemos agrupar por todas, exceto as colunas especificadas
Em [12]: grouped.sum()
Fora[12]:
(continua na próxima página)
C D
A
barra -1,591710 -1,739537
foo -0,752861 -1,402938
Isso dividirá o DataFrame em seu índice (linhas). Também poderíamos dividir pelas colunas:
Os objetos de índice do pandas suportam valores duplicados. Se um índice não exclusivo for usado como chave de grupo em uma operação groupby,
todos os valores para o mesmo valor de índice serão considerados em um grupo e, portanto, a saída das funções de agregação
conterá apenas valores de índice exclusivos:
Em [18]: grouped.first()
Fora[18]:
11
22
33
tipo d: int64
Em [19]: grouped.last()
Fora[19]:
1 10
2 20
3 30
tipo d: int64
Em [20]: grouped.sum()
Fora[20]:
1 11
2 22
3 33
tipo d: int64
Observe que nenhuma divisão ocorre até que seja necessária. A criação do objeto GroupBy apenas verifica se você passou um valor válido
mapeamento.
Nota: Muitos tipos de manipulações complicadas de dados podem ser expressas em termos de operações GroupBy (embora não possam
ser garantidamente a mais eficiente). Você pode ser bastante criativo com as funções de mapeamento de rótulos.
Por padrão, as chaves de grupo são classificadas durante a operação groupby. No entanto, você pode passar sort=False para possíveis
acelerações:
Em [21]: df2 = pd.DataFrame({"X": ["B", "B", "A", "A"], "Y": [1, 2, 3, 4]})
Em [22]: df2.groupby(["X"]).sum()
Fora[22]:
Y
X
Um 7
B3
Observe que groupby preservará a ordem em que as observações são classificadas dentro de cada grupo. Por exemplo, os
grupos criados por groupby() abaixo estão na ordem em que apareceram no DataFrame original:
Em [24]: df3 = pd.DataFrame({"X": ["A", "B", "A", "B"], "Y": [1, 4, 3, 2]})
Em [25]: df3.groupby(["X"]).get_group("A")
Fora[25]:
XY
0A1
2A3
Em [26]: df3.groupby(["X"]).get_group("B")
Saída[26]:
XY 1
B43B2
Por padrão, os valores NA são excluídos das chaves de grupo durante a operação groupby. No entanto, caso você queira incluir valores
NA nas chaves de grupo, você pode passar dropna=False para conseguir isso.
Em [27]: df_list = [[1, 2, 3], [1, Nenhum, 4], [2, 1, 3], [1, 2, 2]]
1 1 NaN 4
2 2 1,0 3
3 1 2,0 2
# Dropna padrão é definido como True, o que excluirá NaNs nas chaves Em [30]:
df_dropna.groupby(by=["b"], dropna=True).sum()
Fora[30]:
ac
b
1,0 2 3
2,0 2 5
# Para permitir NaN nas chaves, defina dropna como False In [31]:
df_dropna.groupby(by=["b"], dropna=False).sum()
Fora[31]:
ac
b 1,0 2 3 2,0
2 5 NaN 1 4
A configuração padrão do argumento dropna é True, o que significa que NA não está incluído nas chaves de grupo.
O atributo groups é um dict cujas chaves são os grupos únicos computados e os valores correspondentes são os rótulos
dos eixos pertencentes a cada grupo. No exemplo acima temos:
Chamar a função len padrão do Python no objeto GroupBy apenas retorna o comprimento do ditado de grupos, portanto,
é apenas uma conveniência:
Em [36]: len(agrupado)
Fora[36]: 6
Em [37]: df
Fora[37]:
altura peso sexo masculino
01/01/2000 42,849980 157,500553
(continua na próxima página)
Em [38]: gb = df.groupby("gênero")
Com dados indexados hierarquicamente, é bastante natural agrupar por um dos níveis da hierarquia.
Em [40]: matrizes = [
....: ["bar", "bar", "baz", "baz", "foo", "foo", "qux", "qux"],
....: ["um", "dois", "um ", "dois ", "um" , " dois", "um", "dois"],
....: ]
....:
Em [43]: s
Fora[43]:
primeiro segundo
bar um -0,919854
dois -0,042379
baz um 1.247642
dois -0,009920
foo um 0,290213
dois 0,495767
qx um 0,362949
dois 1.548106
tipo d: float64
Em [45]: grouped.sum()
Fora[45]:
primeiro
barra -0,962232
baz 1.237723
foo 0,785980
qux 1.911055
dtype: float64
Se o MultiIndex tiver nomes especificados, estes podem ser passados em vez do número do nível:
Em [46]: s.groupby(level="second").sum()
Fora[46]:
segundo
um 0,980950
dois 1.991575
tipo d: float64
Em [47]: s
Fora[47]:
primeiro segundo terceiro
bar doo um -1,131345
dois -0,089329
baz abelha um 0,337863
dois -0,945867
foo bop um -0,932132
dois 1.956030
qx bop um 0,017587
dois -0,016692
tipo d: float64
Um DataFrame pode ser agrupado por uma combinação de colunas e níveis de índice, especificando os nomes das colunas como strings
e os níveis de índice como objetos pd.Grouper.
Em [50]: matrizes = [
....: ["bar", "bar", "baz", "baz", "foo", "foo", "qux", "qux"],
....: ["um", "dois", "um ", "dois ", "um" , " dois", "um", "dois"],
....: ]
....:
Em [53]: df
Fora[53]:
AB
primeiro segundo
barra um 10
dois 11
baz um 12
dois 13
foo um 24
dois 25
qx um 36
dois 37
segundo A
um 12
24
36
dois 14
2 5
37
Os nomes dos níveis de índice podem ser especificados como chaves diretamente para groupby.
Depois de criar o objeto GroupBy a partir de um DataFrame, você pode querer fazer algo diferente para cada um deles.
as colunas. Assim, usando [] semelhante a obter uma coluna de um DataFrame, você pode fazer:
Em [57]: df = pd.DataFrame(
....: {
....: "A": ["foo", "bar", "foo", "bar", "foo", "bar", "foo", "foo"],
....: "B": ["um", "um", "dois", "três", "dois", "dois", "um", "três"],
....: "C": np.random.randn(8),
....: "D": np.random.randn(8),
....: }
....: )
....:
Em [58]: df
Fora[58]:
DE ANÚNCIOS B C
0 foo um -0,575247 1,346061
1 barra um 0,254161 1,511763
2 pés dois -1,143704 1,627081
3 barra três 0,215897 -0,990582
4 pés dois 1,193555 -0,441652
5 barras dois -0,077118 1,211526
6 foo um -0,408530 0,268520
7 foo três -0,862495 0,024580
Em [62]: df["C"].groupby(df["A"])
Out[62]: <objeto pandas.core.groupby.generic.SeriesGroupBy em 0x7f0eaf5addc0>
Além disso, este método evita recalcular as informações de agrupamento interno derivadas da chave passada.
Com o objeto GroupBy em mãos, iterar pelos dados agrupados é muito natural e funciona de maneira semelhante a
itertools.groupby():
A B C D
0 foo um -0,575247 1,346061
2 pés dois -1,143704 1,627081
4 pés dois 1,193555 -0,441652
6 foo um -0,408530 0,268520
7 foo três -0,862495 0,024580
No caso de agrupamento por múltiplas chaves, o nome do grupo será uma tupla:
Em [66]: grouped.get_group("bar")
Fora[66]:
A B C D
1 barra um 0,254161 1,511763
3 barra três 0,215897 -0,990582
5 barras dois -0,077118 1,211526
2.18.4 Agregação
Depois que o objeto GroupBy for criado, vários métodos estarão disponíveis para realizar um cálculo no objeto agrupado.
dados. Essas operações são semelhantes à API de agregação, à API de janela e à API de reamostragem.
Em [69]: agrupado.agregado(np.sum)
Fora[69]:
C D
A
barra 0,392940 1,732707
foo -1,796421 2,824590
Em [71]: agrupado.agregado(np.sum)
Fora[71]:
C D
AB
(continua na próxima página)
Como você pode ver, o resultado da agregação terá os nomes dos grupos como o novo índice ao longo do eixo agrupado. No
caso de múltiplas chaves, o resultado é um MultiIndex por padrão, embora isso possa ser alterado usando a opção as_index:
Em [73]: agrupado.agregado(np.sum)
Fora[73]:
DE ANÚNCIOS B C
0 barra um 0,254161 1,511763
1 barra três 0,215897 -0,990582
2 barras dois -0,077118 1,211526
3 foo um -0,983776 1,614581
4 foo três -0,862495 0,024580
5 foo dois 0,049851 1,185429
Observe que você pode usar a função reset_index DataFrame para obter o mesmo resultado que os nomes das colunas são
armazenado no MultiIndex resultante:
Outro exemplo simples de agregação é calcular o tamanho de cada grupo. Isso está incluído no GroupBy como o tamanho
método. Retorna uma Série cujo índice são os nomes dos grupos e cujos valores são os tamanhos de cada grupo.
Em [76]: grouped.size()
Fora[76]:
Tamanho B
A0 um 1
compasso 1 1
compasso dois 1
três 2 um 2
compasso 3 foo 4 1
foo três 5 foo dois 2
Em [77]: grouped.describe()
Fora[77]:
C ... D ÿ
ÿÿ
[6 linhas x 16 colunas]
Outro exemplo de agregação é calcular o número de valores exclusivos de cada grupo. Isto é semelhante ao
função value_counts, exceto que conta apenas valores únicos.
Em [78]: ll = [['foo', 1], ['foo', 2], ['foo', 2], ['bar', 1], ['bar', 1]]
Em [80]: df4
Fora[80]:
AB
0 foo 1
1 foo 2
2 foo 2
3 barra 1
4 barra 1
Em [81]: df4.groupby("A")["B"].nunique()
Fora[81]:
A
bar 1
foo 2
Nome: B, dtype: int64
Nota: As funções de agregação não retornarão os grupos sobre os quais você está agregando se eles forem colunas nomeadas, quando
as_index=True, o padrão. As colunas agrupadas serão os índices do objeto retornado.
Passar as_index=False retornará os grupos que você está agregando, se eles forem colunas nomeadas.
Funções agregadoras são aquelas que reduzem a dimensão dos objetos retornados. Algumas agregações comuns
funções estão tabeladas abaixo:
Função Descrição
média() Calcular média de grupos
soma() Calcular a soma dos valores do grupo
tamanho() Calcular tamanhos de grupo
contagem() Calcular contagem do grupo
std() Desvio padrão dos grupos
var() Calcular variância de grupos
sem() Erro padrão da média dos grupos
descrever() Gera estatísticas descritivas
primeiro() Calcule o primeiro dos valores do grupo
último() Calcular o último valor do grupo
nth() Pegue o enésimo valor ou um subconjunto se n for uma lista
As funções de agregação acima excluirão os valores NA. Qualquer função que reduz uma série a um valor escalar é uma
função de agregação e funcionará, um exemplo trivial é df.groupby('A').agg(lambda ser: 1). Observe que nth()
pode atuar como redutor ou filtro, veja aqui.
Com séries agrupadas você também pode passar uma lista ou ditado de funções para agregar, gerando um DataFrame:
A
barra 0,392940 0,130980 0,181231
foo -1,796421 -0,359284 0,912265
Em um DataFrame agrupado, você pode passar uma lista de funções para aplicar a cada coluna, o que produz um valor agregado
resultado com um índice hierárquico:
A
barra 0,392940 0,130980 0,181231 1,732707 0,577569 1,366330
foo -1,796421 -0,359284 0,912265 2,824590 0,564918 0,884785
As agregações resultantes são nomeadas de acordo com as próprias funções. Se precisar renomear, você pode adicionar um encadeado
operação para uma série como esta:
Em [85]: (
....: agrupado["C"]
....: .agg([np.sum, np.mean, np.std])
....: .rename(colunas={"sum": "foo", "mean": "bar", "std": "baz"})
....: )
....:
(continua na próxima página)
Fora[85]:
foo bar baz
A
barra 0,392940 0,130980 0,181231
foo -1,796421 -0,359284 0,912265
Em [86]: (
....: agrupado[["C", "D"]].agg([np.sum, np.mean, np.std]).rename(
....: colunas={"sum": "foo", "mean": "bar", "std": "baz"}
....: )
....: )
....:
Fora[86]:
D
C foo bar baz foo bar baz
A
barra 0,392940 0,130980 0,181231 1,732707 0,577569 1,366330
foo -1,796421 -0,359284 0,912265 2,824590 0,564918 0,884785
Nota: Em geral, os nomes das colunas de saída devem ser exclusivos. Você não pode aplicar a mesma função (ou duas funções
com o mesmo nome) para a mesma coluna.
pandas permite fornecer vários lambdas. Neste caso, os pandas irão alterar o nome do lambda (sem nome)
funções, anexando _<i> a cada lambda subsequente.
Agregação nomeada
Para suportar agregação específica de coluna com controle sobre os nomes das colunas de saída, o pandas aceita a sintaxe especial
em GroupBy.agg(), conhecido como “agregação nomeada”, onde
• Os valores são tuplas cujo primeiro elemento é a coluna a ser selecionada e o segundo elemento é a agregação a ser aplicada
para essa coluna. pandas fornece ao pandas.NamedAgg nomeadotuple os campos ['column', 'aggfunc']
para deixar mais claro quais são os argumentos. Como de costume, a agregação pode ser um alias chamável ou de string.
Em [90]: animais
Fora[90]:
tipo altura peso
0 gato 9,1 7,9
1 cachorro 6,0 7,5
2 gato 9,5 9,9
3 cachorro 34,0 198,0
Em [91]: animais.groupby("tipo").agg(
....: min_height=pd.NamedAgg(coluna="altura", aggfunc="min"),
....: max_height=pd.NamedAgg(coluna="altura", aggfunc="max"),
....: peso_médio=pd.NamedAgg(coluna="peso", aggfunc=np.mean),
....: )
....:
Fora[91]:
min_height max_height peso_médio
tipo
gato 9.1 9,5 8,90
cachorro 6,0 34,0 102,75
pandas.NamedAgg é apenas uma tupla nomeada. Tuplas simples também são permitidas.
Em [92]: animais.groupby("tipo").agg(
....: min_height=("altura", "min"),
....: max_height=("altura", "máx"),
....: peso_médio=("peso", np.mean),
....: )
....:
Fora[92]:
min_height max_height peso_médio
tipo
gato 9.1 9,5 8,90
cachorro 6,0 34,0 102,75
Se os nomes das colunas de saída desejadas não forem palavras-chave Python válidas, construa um dicionário e descompacte a palavra-chave
argumentos
Em [93]: animais.groupby("tipo").agg(
....: **{
....: "peso total": pd.NamedAgg(column="peso", aggfunc=sum)
....: }
....: )
....:
Fora[93]:
peso total
tipo
gato 17,8
cachorro 205,5
Argumentos adicionais de palavras-chave não são passados para as funções de agregação. Apenas pares de (coluna,
aggfunc) deve ser passado como **kwargs. Se suas funções de agregação exigirem argumentos adicionais, aplique parcialmente
eles com functools.partial().
Nota: Para Python 3.5 e versões anteriores, a ordem de **kwargs em funções não foi preservada. Isto significa que a saída
a ordem das colunas não seria consistente. Para garantir uma ordenação consistente, as chaves (e, portanto, as colunas de saída) sempre serão
ser classificado para Python 3.5.
A agregação nomeada também é válida para agregações agrupadas em série. Neste caso não há seleção de coluna, então os valores
são apenas as funções.
Em [94]: animais.groupby("tipo").height.agg(
....: min_height="min",
....: max_height = "máx",
....: )
....:
Fora[94]:
altura_min_altura_máxima
tipo
gato 9,1 9,5
cachorro 6,0 34,0
Ao passar um dict para agregar você pode aplicar uma agregação diferente às colunas de um DataFrame:
Os nomes das funções também podem ser strings. Para que uma string seja válida ela deve ser implementada em GroupBy ou
disponível via despacho:
Algumas agregações comuns, atualmente apenas soma, média, padrão e sem, otimizaram implementações Cython:
Em [97]: df.groupby("A").sum()
Fora[97]:
C D
A
barra 0,392940 1,732707 foo
-1,796421 2,824590
É claro que soma e média são implementadas em objetos pandas, então o código acima funcionaria mesmo sem as versões especiais via
despacho (veja abaixo).
Os usuários também podem fornecer suas próprias funções para agregações personalizadas. Ao agregar com uma função definida
pelo usuário (UDF), a UDF não deve alterar a série fornecida; consulte Mutação com métodos de função definida pelo usuário (UDF)
para obter mais informações.
O dtype resultante refletirá o da função de agregação. Se os resultados de grupos diferentes tiverem dtypes diferentes, então um dtype comum
será determinado da mesma forma que a construção do DataFrame.
tipo
gato 18
cachorro 40
2.18.5 Transformação
O método transform retorna um objeto indexado do mesmo (mesmo tamanho) que aquele que está sendo agrupado. A transformação
função deve:
• Retornar um resultado que seja do mesmo tamanho do bloco do grupo ou que possa ser transmitido para o tamanho do bloco do grupo
(por exemplo, um escalar, grouped.transform(lambda x: x.iloc[-1])).
• Operar coluna por coluna no bloco do grupo. A transformação é aplicada ao primeiro pedaço do grupo usando
pedaço.apply.
• Não realizar operações no local no bloco do grupo. Os pedaços do grupo devem ser tratados como imutáveis e as alterações
para um pedaço de grupo pode produzir resultados inesperados. Por exemplo, ao usar fillna, inplace deve ser False
(agrupado.transform(lambda x: x.fillna(inplace=False))).
• (Opcionalmente) opera em todo o bloco do grupo. Se isso for suportado, um caminho rápido será usado a partir do segundo
pedaço.
Semelhante às agregações com funções definidas pelo usuário, o dtype resultante refletirá o da função de transformação.
Se os resultados de grupos diferentes tiverem tipos diferentes, então um tipo comum será determinado da mesma maneira que
Construção de DataFrame.
Em [104]: ts.head()
Fora[104]:
2000-01-08 0,779333
2000-01-09 0,778852
2000-01-10 0,786476
2000-01-11 0,782797
2000-01-12 0,798110
Freq: D, dtype: float64
Em [105]: ts.tail()
Fora[105]:
30/09/2002 0,660294
01-10-2002 0,631095
02-10-2002 0,673601
03/10/2002 0,709213
04-10-2002 0,719369
Freq: D, tipo d: float64
..... :)
.....:
Esperamos que o resultado agora tenha média 0 e desvio padrão 1 dentro de cada grupo, o que podemos verificar facilmente:
# Dados Originais
Em [107]: agrupado = ts.groupby(lambda x: x.ano)
Em [108]: grouped.mean()
Fora[108]:
2000 0,442441
2001 0,526246
2002 0,459365
tipo d: float64
Em [109]: grouped.std()
Fora[109]:
2000 0,131752
2001 0,210945
2002 0,128753
tipo d: float64
# Dados transformados
Em [110]: grouped_trans = transformado.groupby(lambda x: x.ano)
Em [111]: grouped_trans.mean()
Fora[111]:
2000 1.193722e-15
2001 1.945476e-15
2002 1.272949e-15
tipo d: float64
Em [112]: grouped_trans.std()
Fora[112]:
2000 1,0
2001 1.0
2002 1.0
tipo d: float64
Em [114]: compare.plot()
Saída[114]: <AxesSubplot:>
Funções de transformação que possuem saídas de dimensão inferior são transmitidas para corresponder ao formato da matriz de entrada.
Alternativamente, os métodos integrados podem ser usados para produzir os mesmos resultados.
Fora[118]:
08/01/2000 0,623893
09/01/2000 0,623893
10/01/2000 0,623893
11/01/2000 0,623893
12/01/2000 0,623893
...
30/09/2002 0,558275
01-10-2002 0,558275
02-10-2002 0,558275
03/10/2002 0,558275
04/10/2002 0,558275
Freq: D, Comprimento: 1001, tipo d: float64
Outra transformação de dados comum é substituir os dados ausentes pela média do grupo.
Em [119]: dados_df
Fora[119]:
A B C
0 1,539708 -1,166480 0,533026
1 1,302092 -0,505754 NaN
2 -0,371983 1,104803 -0,651520
3 -1,309622 1,118697 -1,161657
4 -1,924296 0,396437 0,812436
.. ... ... ...
995 -0,093110 0,683847 -0,774753
996 -0,185043 1,438572 NaN
997 -0,394469 -0,642343 0,011374
998 -1,174126 1,857148 999 NaN
0,234564 0,517098 0,393534
Podemos verificar que as médias do grupo não mudaram nos dados transformados e que os dados transformados contêm
sem NA.
EUA 258
tipo d: int64
Nota: Algumas funções transformarão automaticamente a entrada quando aplicadas a um objeto GroupBy, mas retornarão um
objeto com a mesma forma do original. Passar as_index=False não afetará esses métodos de transformação.
Em [131]: grouped.ffill()
Fora[131]:
A B C
0 1,539708 -1,166480 0,533026
1 1,302092 -0,505754 0,533026
(continua na próxima página)
O exemplo abaixo aplicará o método rolling() nas amostras da coluna B com base nos grupos de colunas
A.
Em [133]: df_re
Fora[133]:
A B
0 1 0
1 1 1
2 1 2
3 1 3
4 1 4
.. .. ..
15 5 15
16 5 16
17 5 17
18 5 18
19 5 19
Em [134]: df_re.groupby("A").rolling(4).B.mean()
Fora[134]:
A
101 NaN
NaN
NaN
1,5
234 2,5
...
5 15 16 13,5
14,5
17 15,5
(continua na próxima página)
18 16,5
19 17,5
Nome: B, Comprimento: 20, dtype: float64
O método expandindo() acumulará uma determinada operação (sum() no exemplo) para todos os membros de cada
determinado grupo.
Em [135]: df_re.groupby("A").expanding().sum()
Fora[135]:
B
A
10 0,0
1,0
3,0
123 6,0
4 10,0
... ...
5 15 75,0
16 91,0
17 108,0
18 126,0
19 145,0
Suponha que você queira usar o método resample() para obter uma frequência diária em cada grupo do seu dataframe e desejar
para completar os valores ausentes com o método ffill().
Em [137]: df_re
Fora[137]:
valor do grupo
data
03/01/2016 1 5
10/01/2016 1 6
17/01/2016 2 7
24/01/2016 2 8
Em [138]: df_re.groupby("grupo").resample("1D").ffill()
Fora[138]:
valor do grupo
data do grupo
1 03/01/2016 5
04/01/2016 11 5
(continua na próxima página)
05/01/2016 1 5
06/01/2016 1 5
07/01/2016 1 5
... ... ...
2 20/01/2016 2 7
21/01/2016 2 7
22/01/2016 2 7
23/01/2016 2 7
24/01/2016 2 8
2.18.6 Filtragem
O método filter retorna um subconjunto do objeto original. Suponha que queiramos pegar apenas elementos que pertencem a
grupos com soma de grupo maior que 2.
O argumento do filtro deve ser uma função que, aplicada ao grupo como um todo, retorne Verdadeiro ou Falso.
Outra operação útil é filtrar elementos que pertencem a grupos com apenas alguns membros.
Alternativamente, em vez de descartar os grupos ofensivos, podemos retornar objetos indexados de forma semelhante, onde os grupos que o fazem
não passam no filtro são preenchidos com NaNs.
6 NaN NaN
7 NaN NaN
Para DataFrames com múltiplas colunas, os filtros devem especificar explicitamente uma coluna como critério de filtro.
44b4
55b5
Nota: Algumas funções, quando aplicadas a um objeto groupby, atuarão como um filtro na entrada, retornando uma
forma reduzida do original (e potencialmente eliminando grupos), mas com o índice inalterado. Passar as_index=False
não afetará esses métodos de transformação.
Em [146]: dff.groupby("B").head(2)
Fora[146]:
ABC
00a0
11a1
22b2
33b3
66c6
77c7
Ao fazer uma agregação ou transformação, talvez você queira apenas chamar um método de instância em cada grupo de dados.
Isso é muito fácil de fazer passando funções lambda:
Porém, é bastante detalhado e pode ser confuso se você precisar passar argumentos adicionais. Usando um pouco de inteligência de
metaprogramação, GroupBy agora tem a capacidade de “despachar” chamadas de método para os grupos:
Em [149]: grouped.std()
Fora[149]:
(continua na próxima página)
C D
A
barra 0,181231 1,366330
foo 0,912265 0,884785
O que realmente está acontecendo aqui é que um wrapper de função está sendo gerado. Quando invocado, leva qualquer passado
argumentos e invoca a função com quaisquer argumentos em cada grupo (no exemplo acima, a função std). O
os resultados são então combinados no estilo agg e transform (na verdade, usa apply para inferir a colagem,
documentado a seguir). Isso permite que algumas operações sejam realizadas de forma bastante sucinta:
Em [153]: grouped.fillna(method="pad")
Fora[153]:
abc
2000-01-01 NaN NaN NaN
02/01/2000 -0,353501 -0,080957 -0,876864
03-01-2000 -0,353501 -0,080957 -0,876864
04-01-2000 0,050976 0,044273 -0,559849
05-01-2000 0,050976 0,044273 -0,559849
... ... ... ...
22/09/2002 0,005011 0,053897 -1,026922
23/09/2002 0,005011 0,053897 -1,026922
24/09/2002 -0,456542 -1,849051 1,559856
25/09/2002 -0,456542 -1,849051 1,559856
26/09/2002 1,123162 0,354660 1,128135
Neste exemplo, dividimos a coleção de séries temporais em pedaços anuais e então chamados independentemente de fillna no
grupos.
Em [155]: g = pd.Series(list("abababab"))
Em [156]: gb = s.groupby(g)
Em [157]: gb.nlargest(3)
Fora[157]:
um 4 19,0
0 9,0
(continua na próxima página)
2 7,0
b1 8,0
3 5,0
7 3.3
tipo d: float64
Em [158]: gb.nsmallest(3)
Fora[158]:
um 6 4.2
2 7,0
9,0
0b 5 1,0
7 3.3
3 5,0
tipo d: float64
Algumas operações nos dados agrupados podem não se enquadrar nas categorias agregada ou de transformação. Ou você pode simplesmente
deseja que GroupBy infira como combinar os resultados. Para estes, use a função apply, que pode ser substituída por ambos
agregar e transformar em muitos casos de uso padrão. No entanto, apply pode lidar com alguns casos de uso excepcionais, por
exemplo:
Em [159]: df
Fora[159]:
A B C D
0 foo um -0,575247 1,346061
1 barra um 0,254161 1,511763
2 pés dois -1,143704 1,627081
3 barra três 0,215897 -0,990582
4 pés dois 1,193555 -0,441652
5 barras dois -0,077118 1,211526
6 foo um -0,408530 0,268520
7 foo três -0,862495 0,024580
Em [164]: grouped.apply(f)
Fora[164]:
original humilhado
0 -0,575247 -0,215962
1 0,254161 0,123181
2 -1,143704 -0,784420
3 0,215897 0,084917
4 1,193555 1,552839
5 -0,077118 -0,208098
6 -0,408530 -0,049245
7 -0,862495 -0,503211
aplicar em uma série pode operar em um valor retornado da função aplicada, que é em si uma série e possivelmente upcast
o resultado para um DataFrame:
Em [166]: s = pd.Series(np.random.rand(5))
Em [167]: s
Fora[167]:
0 0,321438
1 0,493496
2 0,139505
3 0,910103
4 0,194158
tipo d: float64
Em [168]: s.apply(f)
Fora[168]:
x x^2
0 0,321438 0,103323
1 0,493496 0,243538
2 0,139505 0,019462
3 0,910103 0,828287
4 0,194158 0,037697
Nota: apply pode atuar como uma função redutora, transformadora ou de filtro, dependendo exatamente do que é passado para ela. Então
dependendo do caminho percorrido e exatamente do que você está agrupando. Assim, as colunas agrupadas podem ser incluídas no
saída, bem como definir os índices.
Semelhante às agregações com funções definidas pelo usuário, o dtype resultante refletirá o da função apply. Se
os resultados de grupos diferentes têm tipos diferentes, então um tipo comum será determinado da mesma maneira que
Construção de DataFrame.
Se o Numba estiver instalado como uma dependência opcional, os métodos de transformação e agregação suportam engine='numba'
e argumentos engine_kwargs. Veja como melhorar o desempenho com Numba para uso geral dos argumentos e
considerações de desempenho.
A assinatura da função deve começar com valores, indexar exatamente como os dados pertencentes a cada grupo serão passados para
valores, e o índice do grupo será passado para index.
Aviso: Ao usar engine='numba', não haverá comportamento de “retrocesso” internamente. Os dados do grupo e
o índice do grupo será passado como matrizes NumPy para a função JITed definida pelo usuário e nenhuma tentativa alternativa de execução
será tentado.
Em [169]: df
Fora[169]:
A B C D
0 foo 1 um -0,575247 1,346061
barra um 0,254161 1,511763
2 pés dois -1,143704 1,627081
3 barra três 0,215897 -0,990582
4 pés dois 1,193555 -0,441652
5 barras dois -0,077118 1,211526
6 foo um -0,408530 0,268520
7 foo três -0,862495 0,024580
Suponha que desejemos calcular o desvio padrão agrupado pela coluna A. Há um pequeno problema, nomeadamente que
não nos importamos com os dados da coluna B. Chamamos isso de coluna “incômodo”. Se a função de agregação passada
não puder ser aplicado a algumas colunas, as colunas problemáticas serão descartadas (silenciosamente). Assim, isto não representa qualquer
problemas:
Em [170]: df.groupby("A").std()
Fora[170]:
C D
A
barra 0,181231 1,366330
foo 0,912265 0,884785
Nota: Qualquer coluna de objeto, mesmo que contenha valores numéricos como objetos Decimais, é considerada um “incômodo”
colunas. Eles são excluídos das funções agregadas automaticamente no groupby.
Se desejar incluir colunas decimais ou de objeto em uma agregação com outros tipos de dados não incômodos, você deverá
faça isso explicitamente.
0,75
12 0,55
# ...mas não podem ser combinados com tipos de dados padrão ou serão excluídos
Em [174]: df_dec.groupby(["id"])[["int_column", "dec_column"]].sum()
Fora[174]:
coluna_int
eu ia
1 4
2 6
1 4 0,75
2 6 0,55
Ao usar uma garoupa categórica (como uma única garoupa ou como parte de várias garoupas), a palavra-chave observada
controla se deve retornar um produto cartesiano de todos os valores possíveis de garoupas (observed=False) ou apenas aqueles que são
garoupas observadas (observado = Verdadeiro).
O dtype retornado do agrupado sempre incluirá todas as categorias que foram agrupadas.
Em [178]: s = (
.....: pd.Série([1, 1, 1])
.....: .groupby(pd.Categorical(["a", "a", "a"], categorias=["a", "b"]),ÿ
ÿÿobservado=Falso)
.....: .contar()
..... :)
.....:
Em [179]: s.index.dtype
Out[179]: CategoricalDtype(categories=['a', 'b'], ordenado=Falso)
Se houver algum valor NaN ou NaT na chave de agrupamento, estes serão automaticamente excluídos. Em outras palavras, haverá
nunca seja um “grupo NA” ou “grupo NaT”. Este não era o caso nas versões mais antigas do pandas, mas os usuários geralmente eram
descartar o grupo de NA de qualquer maneira (e apoiá-lo foi uma dor de cabeça na implementação).
Variáveis categóricas representadas como instância da classe Categorical do pandas podem ser usadas como chaves de grupo. Se assim for, o
a ordem dos níveis será preservada:
Em [182]: data.groupby(fator).mean()
Fora[182]:
(-2,645, -0,523] -1,362896
(-0,523, 0,0296] -0,260266
(0,0296, 0,654] 0,361802
(0,654, 2,21] 1,073801
tipo d: float64
Pode ser necessário especificar um pouco mais de dados para agrupar corretamente. Você pode usar o pd.Grouper para fornecer esse controle local.
Em [184]: df = pd.DataFrame(
.....: {
.....: "Filial": "AAAAAA B".split(),
.....: "Comprador": "Carl Mark Carl Carl Joe Joe Joe Carl".split(),
.....: "Quantidade": [1, 3, 5, 1, 8, 1, 9, 3],
.....: "Data": [
.....: datahora.datehora(2013, 1, 1, 13, 0),
.....: datahora.datehora(2013, 1, 1, 13, 5),
.....: datahora.datehora(2013, 10, 1, 20, 0),
.....: datahora.datehora(2013, 10, 2, 10, 0),
.....: datahora.datehora(2013, 10, 1, 20, 0),
.....: datahora.datehora(2013, 10, 2, 10, 0),
.....: datahora.datehora(2013, 12, 2, 12, 0),
.....: datahora.datehora(2013, 12, 2, 14, 0),
.....: ],
.....: }
..... :)
.....:
Em [185]: df
Fora[185]:
Quantidade do comprador da filial Data
0 Um Carl 101/01/2013 13:00:00
(continua na próxima página)
Agrupar por uma coluna específica com a frequência desejada. Isso é como reamostrar.
31/01/2013 Carlos 1
Marca 3
31/10/2013 Carlos 6
Joe 9
31/12/2013 Carlos 3
Joe 9
Você tem uma especificação ambígua, pois possui um índice nomeado e uma coluna que pode ser garoupas em potencial.
Em [187]: df = df.set_index("Data")
28/02/2013 Carlos 1
Marca 3
28/02/2014 Carlos 9
Joe 18
31/01/2013 Carlos 1
Marca 3
31/01/2014 Carlos 9
Joe 18
Assim como para um DataFrame ou Série, você pode chamar head e tail em um groupby:
Em [192]: df
Fora[192]:
AB
01211
4256
Em [193]: g = df.groupby("A")
Em [194]: g.head(1)
Fora[194]:
AB 0
12256
Em [195]: g.tail(1)
Fora[195]: AB
114
256
Para selecionar em um DataFrame ou Série o enésimo item, use nth(). Este é um método de redução e retornará uma única linha (ou
nenhuma linha) por grupo se você passar um int para n:
Em [197]: g = df.groupby("A")
Em [198]: g.nth(0)
Fora[198]:
B
A
1 NaN 5
6,0
Em [199]: g.nth(-1)
Fora[199]: B
A 1 4,0
5 6,0
Em [200]: g.nth(1)
(continua na próxima página)
Fora[200]:
B
A
1 4,0
Se você deseja selecionar o enésimo item não nulo, use o dropna kwarg. Para um DataFrame, deve ser 'qualquer' ou 'todos', assim como
você passaria para dropna:
A 1 4,0
5 6,0
Em [202]: g.first()
Fora[202]:
B
A
1 4,0
5 6,0
B
A
1 4,0 5
6,0
Em [204]: g.last()
Fora[204]: B
A 1 4,0
5 6,0
1 4,0
5 6,0
Nome: B, dtype: float64
Tal como acontece com outros métodos, passar as_index=False alcançará uma filtragem, que retorna a linha agrupada.
Em [208]: g.nth(0)
(continua na próxima página)
Fora[208]:
A B
0 1 NaN
2 5 6,0
Em [209]: g.nth(-1)
Fora[209]:
A B
1 1 4,0
2 5 6,0
Você também pode selecionar várias linhas de cada grupo especificando vários enésimos valores como uma lista de inteiros.
# obtém o primeiro, o quarto e o último índice de data para cada mês Em [212]:
df.groupby([df.index.year, df.index.month]).nth([0, 3, -1])
Fora[212]: ab
2014 4 1 1
411
411
5 11
5 11
5 11
611
611611
Para ver a ordem em que cada linha aparece em seu grupo, use o método cumcount:
Em [214]: dfg
Fora[214]:
A0a
1a2
a3b
4b
5 uma
Em [215]: dfg.groupby("A").cumcount()
Fora[215]:
0 0
1 1
(continua na próxima página)
2 2
3 0
4 1
5 3
tipo d: int64
Em [216]: dfg.groupby("A").cumcount(ascendente=Falso)
Fora[216]:
0 3
1 2
2 1
3 1
4 0
5 0
tipo d: int64
Enumerar grupos
Para ver a ordem dos grupos (em oposição à ordem das linhas dentro de um grupo dada por cumcount), você pode usar
ngrupo().
Observe que os números dados aos grupos correspondem à ordem em que os grupos seriam vistos ao iterar sobre o
groupby objeto, não a ordem em que são observados pela primeira vez.
Em [218]: dfg
Fora[218]:
A
0 uma
1 uma
2 uma
3b
4b
5 uma
Em [219]: dfg.groupby("A").ngroup()
Fora[219]:
00
10
20
31
41
50
tipo d: int64
Em [220]: dfg.groupby("A").ngroup(ascendente=Falso)
Fora[220]:
0 1
1 1
2 1
(continua na próxima página)
Plotagem
Groupby também funciona com alguns métodos de plotagem. Por exemplo, suponhamos que suspeitamos que alguns recursos em um DataFrame
podem diferir por grupo, neste caso, os valores na coluna 1 onde o grupo é “B” são 3 superiores em média.
Em [221]: np.random.seed(1234)
Em [225]: df.groupby("g").boxplot()
Fora[225]:
A Subtrama de Eixos(0,1,0,15;0,363636x0,75)
B Subtrama de Eixos(0,536364,0,15;0,363636x0,75)
dtype: objeto
O resultado da chamada do boxplot é um dicionário cujas chaves são os valores da nossa coluna de agrupamento g (“A” e “B”). Os
valores do dicionário resultante podem ser controlados pela palavra-chave return_type do boxplot. Consulte a documentação de
visualização para obter mais informações.
Semelhante à funcionalidade fornecida por DataFrame e Series, funções que usam objetos GroupBy podem ser encadeadas usando um
método pipe para permitir uma sintaxe mais limpa e legível. Para ler sobre .pipe em termos gerais, veja aqui.
Combinar .groupby e .pipe geralmente é útil quando você precisa reutilizar objetos GroupBy.
Como exemplo, imagine ter um DataFrame com colunas de lojas, produtos, receita e quantidade vendida. Gostaríamos de fazer um
cálculo de preços em grupo (ou seja, receita/quantidade) por loja e por produto. Poderíamos fazer isso em uma operação de várias
etapas, mas expressá-lo em termos de tubulação pode tornar o código mais legível. Primeiro definimos os dados:
Em [226]: n = 1000
Em [227]: df = pd.DataFrame(
(continua na próxima página)
Em [228]: df.head(2)
Fora[228]:
Loja Quantidade de receita do produto
0 Loja_2 Produto_1 26,12 1
1 Loja_2 Produto_1 28,86 1
Em [229]: (
.....: df.groupby(["Loja", "Produto"])
.....: .pipe(lambda grp: grp.Revenue.sum() / grp.Quantity.sum())
.....: .unstack()
.....: .2 ª rodada)
..... :)
.....:
Fora[229]:
Produto Produto_1 Produto_2
Loja
Loja_1 6,82 7.05
Loja_2 6h30 6,64
A tubulação também pode ser expressiva quando você deseja entregar um objeto agrupado para alguma função arbitrária, por exemplo:
onde média pega um objeto GroupBy e encontra a média das colunas Receita e Quantidade, respectivamente, para cada
Combinação Loja-Produto. A função média pode ser qualquer função que receba um objeto GroupBy; o .pipe irá
passe o objeto GroupBy como parâmetro para a função que você especificar.
2.18.11 Exemplos
Em [232]: df = pd.DataFrame({"a": [1, 0, 0], "b": [0, 1, 0], "c": [1, 0, 0], "d ": [2, 3,ÿÿ ÿ4]})
Em [233]: df
Fora[233]:
ABCD
01012
10103
20004
Fatoração multicoluna
Usando ngroup(), podemos extrair informações sobre os grupos de uma forma semelhante a factorize() (conforme descrito mais
adiante na API de remodelagem), mas que se aplica naturalmente a múltiplas colunas de tipo misto e fontes diferentes. Isso pode ser
útil como uma etapa intermediária de processamento do tipo categórico, quando os relacionamentos entre as linhas do grupo são
mais importantes que seu conteúdo, ou como entrada para um algoritmo que aceita apenas a codificação inteira. (Para obter mais
informações sobre o suporte em pandas para dados categóricos completos, consulte a introdução categórica e a documentação da API.)
Em [236]: dfg
Fora[236]:
AB
0 1 uma
1 1 uma
2 2 uma
3 3b
4 2 uma
4
1 2 1 tipo de d: int64
Fora[238]: 0
0
1 0
2 1
3 3
4 2
tipo d: int64
A reamostragem produz novas amostras hipotéticas (resamostras) a partir de dados observados já existentes ou de um modelo que
gera dados. Essas novas amostras são semelhantes às amostras pré-existentes.
Para fazer uma nova amostragem para trabalhar em índices que não sejam semelhantes a data e hora, o procedimento a seguir pode ser utilizado.
Nos exemplos a seguir, df.index // 5 retorna um array binário que é usado para determinar o que é selecionado para a operação groupby.
Nota: O exemplo abaixo mostra como podemos reduzir a resolução consolidando as amostras em menos amostras. Aqui, usando
df.index // 5, estamos agregando as amostras em caixas. Ao aplicar a função std() , agregamos as informações contidas em muitas
amostras em um pequeno subconjunto de valores que é o seu desvio padrão, reduzindo assim o número de amostras.
Em [240]: df
Fora[240]:
0 1
0 -0,793893 0,321153
1 0,342250 1,618906
2 -0,975807 1,918201
3 -0,810847 -1,405919
4 -1,977759 0,461659
5 0,730057 -1,316938
6 -0,751328 0,528290
7 -0,257759 -1,081009
8 0,505895 -1,701948
9 -1,006349 0,020208
Agrupe colunas do DataFrame, calcule um conjunto de métricas e retorne uma série nomeada. O nome da série é usado como o nome
para o índice da coluna. Isto é especialmente útil em conjunto com operações de remodelagem, como empilhamento, nas quais o
o nome do índice da coluna será usado como o nome da coluna inserida:
Em [243]: df = pd.DataFrame(
.....: {
.....: "a": [0, 0, 0, 0 , 1, 1, 1, 1, 2, 2, 2, 2],
.....: "b": [0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1],
.....: "c": [1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0],
.....: "d": [0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1],
.....: }
..... :)
.....:
Em [246]: resultado
Fora[246]:
métricas b_sum c_mean
a
0 2,0 0,5
1 2,0 0,5
2 2,0 0,5
Em [247]: result.stack()
Fora[247]:
uma métrica
0 b_soma 2,0
c_média 0,5
1 b_soma 2,0
c_média 0,5
2 b_soma 2,0
c_média 0,5
tipo d: float64
pandas contém um conjunto compacto de APIs para realizar operações de janelas - uma operação que realiza uma agregação
sobre uma partição deslizante de valores. A API funciona de forma semelhante à API groupby naquela chamada Series e DataFrame
o método de janelamento com os parâmetros necessários e, posteriormente, chamar a função de agregação.
Em [1]: s = pd.Series(intervalo(5))
Em [2]: s.rolling(window=2).sum()
(continua na próxima página)
Fora[2]:
0 NaN
1 1,0
2 3,0
3 5,0
4 7,0
tipo d: float64
As janelas são compostas pela observação do comprimento da janela a partir da observação atual. O resultado acima
pode ser derivado tomando a soma das seguintes partições de dados em janelas:
tipo d: int64
00
1 1
tipo d: int64
11
2 2
tipo d: int64
22
3 3
tipo d: int64
33
4 4
tipo d: int64
2. Janela ponderada: janela ponderada não retangular fornecida pela biblioteca scipy.signal.
versão 1.3)
Janela ponderada janela rolante Não Não Não Não
Conforme observado acima, algumas operações suportam a especificação de uma janela com base em um deslocamento de horário:
Em [5]: s.rolling(window='2D').sum()
Fora[5]:
01/01/2020 0,0
2020-01-02 1,0
2020-01-03 3.0
2020-01-04 5.0
05/01/2020 7,0
Freq: D, tipo d: float64
Além disso, alguns métodos suportam o encadeamento de uma operação groupby com uma operação de janela que primeiro agrupará
os dados pelas chaves especificadas e, em seguida, execute uma operação de janelas por grupo.
Em [7]: df.groupby('A').expanding().sum()
Fora[7]:
B
A
um 0 0,0
2 2,0
4 6,0
b 1 1,0
3 4,0
Nota: Atualmente, as operações de janelas suportam apenas dados numéricos (inteiro e flutuante) e sempre retornarão float64
valores.
Aviso: alguns métodos de agregação de janelas, média, soma, var e std podem sofrer de imprecisão numérica devido aos algoritmos de
janelas subjacentes que acumulam somas. Quando os valores diferem com a magnitude
1/ . isso resulta . truncamento.
( em ). Deve-se notar que grandes valores podem ter um impacto sobre
janelas, que não incluem esses valores. A soma de Kahan é usada para calcular as somas contínuas para preservar
precisão tanto quanto possível.
Algumas operações de janelas também suportam a opção method='table' no construtor que executa a operação de janelas em um DataFrame
inteiro em vez de uma única coluna ou linha por vez. Isto pode fornecer um útil
benefício de desempenho para um DataFrame com muitas colunas ou linhas (com o argumento do eixo correspondente) ou o
capacidade de utilizar outras colunas durante a operação de janelas. A opção method='table' só pode ser usada se
engine='numba' é especificado na chamada de método correspondente.
Por exemplo, um cálculo de média ponderada pode ser calculado com apply() especificando uma coluna separada de pesos.
...:
0 1 2
0 1,000000 2,000000 1,0
1 1,800000 2,000000 1,0
2 3,333333 2,333333 1,0 3 1,555556
7,000000 1,0
Algumas operações de janelamento também suportam um método online após a construção de um objeto de janelamento que
retorna um novo objeto que suporta a passagem de novos objetos DataFrame ou Série para continuar o cálculo de janelamento
com os novos valores (ou seja, cálculos online).
Os métodos nesses novos objetos de janelamento devem chamar primeiro o método de agregação para “preparar” o estado inicial
do cálculo online. Em seguida, novos objetos DataFrame ou Series podem ser passados no argumento de atualização para
continuar o cálculo de janelas.
Em [12]: df.ewm(0.5).mean()
Fora[12]:
0 1 2
0 1,000000 2,000000 0,600000
1 1,750000 2,750000 0,450000 2 2,615385
3,615385 0,276923 3 3,550000 4,550000
0,562500
Em [14]: online_ewm.mean()
Fora[14]: 0
1 2
0 1,00 2,00 0,60
1 1,75 2,75 0,45
Em [15]: online_ewm.mean(update=df.tail(1))
Fora[15]:
0 1 2
3 3,307692 4,307692 0,623077
Todas as operações de janelas suportam um argumento min_periods que determina a quantidade mínima de valores não-np.nan
que uma janela deve ter; caso contrário, o valor resultante será np.nan. min_periods tem como padrão 1 para janelas baseadas
em tempo e janela para janelas fixas
Fora[17]:
0 NaN
1 1,0
2 3,0
3 3,0
4 2,0
5 3,0
tipo d: float64
# Equivalente a min_periods=3
Em [19]: s.rolling(window=3, min_periods=None).sum()
Fora[19]:
0 NaN
1 NaN
2NaN
3NaN
4NaN
5NaN
tipo d: float64
Além disso, todas as operações de janelas suportam o método agregado para retornar um resultado de múltiplas agregações
aplicado a uma janela.
Em [24]: s
Fora[24]:
01/01/2020 0
03/01/2020 1
04/01/2020 2
05/01/2020 3
29/01/2020 tipo 4
d: int64
Centralizando janelas
Por padrão, os rótulos são definidos na borda direita da janela, mas uma palavra-chave central está disponível para que os rótulos possam ser definidos
no centro.
Em [27]: s = pd.Series(intervalo(10))
Em [28]: s.rolling(window=5).mean()
Fora[28]:
0 NaN
1 NaN
2 NaN
3 NaN
(continua na próxima página)
4 2,0
5 3,0
6 4,0
7 5,0
8 6,0
9 7,0
tipo d: float64
Em [30]: df = pd.DataFrame(
....: {"A": [0, 1, 2, 3, 4]}, index=pd.date_range("2020", períodos=5, freq="1D")
....: )
....:
Em [31]: df
Fora[31]:
A
2020-01-01 0
2020-01-02 1
2020-01-03 2
2020-01-04 3
2020-01-05 4
A inclusão dos pontos finais do intervalo nos cálculos da janela rolante pode ser especificada com o parâmetro fechado:
Valor Comportamento
Por exemplo, ter o ponto final correto aberto é útil em muitos problemas que exigem que não haja contaminação
das informações atuais para as informações passadas. Isso permite que a janela contínua calcule estatísticas “até aquele
momento”, mas não incluindo esse momento.
Em [34]: df = pd.DataFrame(
....: {"x": 1},
....: índice=[
....: pd.Timestamp("20130101 09:00:01"),
....: pd.Timestamp("20130101 09:00:02"),
....: pd.Timestamp("20130101 09:00:03"),
....: pd.Timestamp("20130101 09:00:04"),
....: pd.Timestamp("20130101 09:00:06"),
....: ],
....: )
....:
Em [39]: df
Fora[39]:
x direita ambos esquerda nem
01-01-2013 09:00:01 1 01-01-2013 1,0 1,0 NaN 2,0 2,0 1,0 NaN
09:00:02 1 01-01-2013 09:00:03 1 2,0 3,0 2,0 2,0 3,0 2,0 1,0
01-01-2013 09:00:04 1 01-01-2013 1,0 2,0 1,0 1,0
09 :00:06 1 1,0
NaN
Além de aceitar um número inteiro ou deslocamento como argumento de janela, roll também aceita uma subclasse BaseIndexer
que permite ao usuário definir um método personalizado para calcular os limites da janela. A subclasse BaseIndexer precisará
para definir um método get_window_bounds que retorna uma tupla de dois arrays, sendo o primeiro os índices iniciais do
janelas e em segundo lugar os índices finais das janelas. Além disso, num_values, min_periods, center,
fechado e será passado automaticamente para get_window_bounds e o método definido deve sempre aceitar estes
argumentos.
Em [41]: use_expanding
Out[41]: [Verdadeiro, Falso, Verdadeiro, Falso, Verdadeiro]
Em [43]: df
Fora[43]:
valores
0 0
1 1
2 2
3 3
4 4
e queremos usar uma janela de expansão onde use_expanding é True, caso contrário, uma janela de tamanho 1, podemos criar
a seguinte subclasse BaseIndexer:
Em [5]: df.rolling(indexer).sum()
Fora[5]:
valores
0 0,0
1 1,0
2 3,0
(continua na próxima página)
3 3,0
4 10,0
Uma subclasse digna de nota nesses exemplos é a VariableOffsetWindowIndexer, que permite operações contínuas em um deslocamento
não fixo, como BusinessDay.
Em [48]: df
Fora[48]:
0
2020-01-01 0
2020-01-02 1
2020-01-03 2
2020-01-04 3
2020-01-05 4
2020-01-06 5
2020-01-07 6
2020-01-08 7
2020-01-09 8
2020-01-10 9
Em [49]: df.rolling(indexer).sum()
Fora[49]:
0 01/01/2020 0,0
02/01/2020 1,0
03/01/2020 2,0
04/01/2020 3,0
05/01/2020 7,0
06/01/2020 12,0
07/01/2020 6,0
08/01/2020 7,0
2020-01-09 8.0
2020-01-10 9,0
Para alguns problemas, o conhecimento do futuro está disponível para análise. Por exemplo, isso ocorre quando cada ponto de dados é uma
série temporal completa lida de um experimento e a tarefa é extrair condições subjacentes. Nestes casos, pode ser útil realizar cálculos de
janelas contínuas prospectivas. A classe FixedForwardWindowIndexer está disponível para essa finalidade. Esta subclasse BaseIndexer
implementa uma janela contínua fechada de largura fixa e podemos usá-la da seguinte maneira:
Também podemos conseguir isso usando fatiamento, aplicando agregação contínua e, em seguida, invertendo o resultado, conforme mostrado no exemplo
abaixo:
Em [53]: df = pd.DataFrame(
....: dados=[
....: [pd.Timestamp("01/01/2018 00:00:00"), 100],
....: [pd.Timestamp("01/01/2018 00:00:01"), 101],
....: [pd.Timestamp("01/01/2018 00:00:03"), 103],
....: [pd.Timestamp("01/01/2018 00:00:04"), 111],
....: ],
....: colunas=["hora", "valor"],
....: ).set_index("tempo")
....:
Em [54]: df
Fora[54]:
valor
tempo
01-01-2018 00:00:00 100
01-01-2018 00:00:01 101
01-01-2018 00:00:03 103
01-01-2018 00:00:04 111
Em [56]: invertido_df
Fora[56]:
valor
tempo
01/01/2018 00:00:00 201,0
01/01/2018 00:00:01 101,0
01/01/2018 00:00:03 214,0
01/01/2018 00:00:04 111,0
Aplicação de rolamento
A função apply() recebe um argumento func extra e executa cálculos contínuos genéricos. O argumento funcional
deve ser uma função única que produza um único valor a partir de uma entrada ndarray. raw especifica se as janelas são
lançado como objetos Series (raw=False) ou objetos ndarray (raw=True).
Em [58]: s = pd.Series(intervalo(10))
Motor Numba
Além disso, apply() pode aproveitar o Numba se instalado como uma dependência opcional. A agregação de aplicação pode ser
executado usando Numba especificando os argumentos engine='numba' e engine_kwargs (raw também deve ser definido como
Verdadeiro). Consulte melhorando o desempenho com Numba para uso geral dos argumentos e considerações de desempenho.
1. Se func for uma função padrão do Python, o mecanismo fará o JIT da função passada. func também pode ser uma função JITed
nesse caso, o motor não executará o JIT novamente.
2. O mecanismo fará JIT no loop for onde a função apply é aplicada a cada janela.
O argumento engine_kwargs é um dicionário de argumentos de palavras-chave que serão passados para o decorador numba.jit.
Esses argumentos de palavra-chave serão aplicados à função passada (se for uma função Python padrão) e ao aplicativo para
faça um loop sobre cada janela.
média, mediana, máximo, mínimo e soma também suportam os argumentos motor e motor_kwargs.
cov() e corr() podem calcular estatísticas de janelas móveis sobre duas séries ou qualquer combinação de
DataFrame/Series ou DataFrame/DataFrame. Aqui está o comportamento em cada caso:
• DataFrame/Series: calcula as estatísticas para cada coluna do DataFrame com a Series passada, assim
retornando um DataFrame.
• DataFrame/DataFrame: por padrão calcula a estatística para correspondência de nomes de colunas, retornando um
DataFrame. Se o argumento da palavra-chave pairwise=True for passado, então calcula a estatística para cada par de
colunas, retornando um DataFrame com um MultiIndex cujos valores são as datas em questão (veja a próxima seção).
Por exemplo:
Em [60]: df =
....: pd.DataFrame( np.random.randn(10, 4),
....: index=pd.date_range("2020-01-01", períodos=10), colunas=["A", "B
....: ", "C", "D"],
....: )
....:
Em [61]: df = df.cumsum()
Em [63]: df2.rolling(window=2).corr(df2["B"])
Fora[63]:
A B C D
2020-01-01 NaN NaN NaN NaN
2020-01-02 -1,0 1,0 -1,0 1,0
2020-01-03 1,0 1,0 1,0 -1,0
2020-01-04 -1,0 1,0 1,0 -1,0
Na análise de dados financeiros e em outras áreas, é comum calcular matrizes de covariância e correlação para uma coleção de
séries temporais. Freqüentemente, também se está interessado em matrizes de covariância e correlação de janela móvel. Isso
pode ser feito passando o argumento da palavra-chave pairwise, que no caso de entradas do DataFrame produzirá um DataFrame
MultiIndexado cujo índice são as datas em questão. No caso de um único argumento DataFrame, o argumento pairwise pode até
ser omitido:
Nota: Os valores omissos são ignorados e cada entrada é calculada usando as observações completas aos pares. Consulte a
seção de covariância para obter advertências associadas a este método de cálculo de matrizes de covariância e correlação.
Em [65]: covs
Fora[65]:
B C D
01/01/2020 NaN NaN NaN
B NaN NaN NaN
C NaN NaN NaN
2020-01-02 NaN NaN NaN
B NaN NaN NaN
... ... ... ...
2020-01-09 B 0,342006 0,230190 0,052849
C 0,230190 1,575251 0,082901
2020-01-10 UM -0,333945 0,006871 -0,655514
B 0,649711 0,430860 0,469271
C 0,430860 0,829721 0,055300
O argumento win_type em .rolling gera janelas ponderadas que são comumente usadas em filtragem e espectro
estimativa. win_type deve ser uma string que corresponda a uma função de janela scipy.signal. O Scipy deve ser instalado em
para usar essas janelas, e argumentos suplementares que os métodos de janela do Scipy usam devem ser especificados em
a função de agregação.
Em [66]: s = pd.Series(intervalo(10))
Em [67]: s.rolling(window=5).mean()
Fora[67]:
0 NaN
NaN
1 NaN
2 3 NaN
4 2,0
5 3,0
6 4,0
7 5,0
8 6,0
9 7,0
tipo d: float64
Uma janela em expansão produz o valor de uma estatística de agregação com todos os dados disponíveis até aquele momento.
Como esses cálculos são um caso especial de estatísticas contínuas, eles são implementados em pandas de forma que o seguinte
duas chamadas são equivalentes:
Em [70]: df = pd.DataFrame(intervalo(5))
Em [72]: df.expanding(min_periods=1).mean()
Fora[72]:
0
0 0,0
1 0,5
2 1,0
3 1,5
4 2,0
Uma janela ponderada exponencialmente é semelhante a uma janela em expansão, mas com cada ponto anterior sendo exponencialmente
ponderado em relação ao ponto atual.
= ÿÿ =0 -
,
ÿÿ =0
Para todas as funções de agregação suportadas, consulte Funções de janela ponderadas exponencialmente.
As funções EW suportam duas variantes de pesos exponenciais. O padrão, Adjust=True, usa os pesos =
(1 ÿ ) que dá
2
= + (1 ÿ ) ÿ1 + (1 ÿ ) ÿ2 +… + (1 ÿ ) 0
2
1 + (1 ÿ ) + (1 ÿ ) + ... + (1 ÿ )
=
0 0
= (1 ÿ ) ÿ1 + ,
se <
(1ÿÿ)) se = .
= {ÿ (1
' =1ÿ
Nota: Essas equações às vezes são escritas em termos de , por exemplo
= '
ÿ1 + (1 ÿ
'
) .
A diferença entre as duas variantes acima surge porque estamos lidando com séries que possuem história finita.
Considere uma série de história infinita, com Adjust=True:
2
= + (1 ÿ ) ÿ1 + (1 ÿ ) ÿ2 + ...
2 + ...
1 + (1 ÿ ) + (1 ÿ )
Observando que o denominador é uma série geométrica com termo inicial igual a 1 e proporção de 1 - temos
2
= + (1 ÿ ) ÿ1 + (1 ÿ ) ÿ2 + ...
1
1ÿ(1ÿ )
2
= [ + (1 ÿ ) ÿ1 + (1 ÿ ) ÿ2 + ...]
2
= + [(1 ÿ ) ÿ1 + (1 ÿ ) ÿ2 + ...] =
+ (1 ÿ )[ ÿ1 + (1 ÿ ) ÿ2 + ...] = + (1 ÿ ) ÿ1
que é a mesma expressão que Adjust=False acima e, portanto, mostra a equivalência das duas variantes para
série infinita. Quando Adjust=False, temos que =
0 0 e = + (1ÿ) ÿ1. Portanto, há uma suposição
não é 0um valor comum, mas sim um momento exponencialmente ponderado da série infinita até aquele ponto.
É preciso ter 0 < ÿ 1 e, embora seja possível passar diretamente, muitas vezes é mais fácil pensar no vão, no centro de massa (com)
ou na meia-vida de um momento EW:
ÿ para vão ÿ 1
2
= para centro de massa ÿ 0
ÿÿ
+1 , 1 1+ ,
registro
ÿÿ 1 ÿ exp
0,5 ÿ
, para meia-vida ÿ > 0
Deve-se especificar precisamente amplitude , centro de massa, meia-vida e alfa para as funções EW:
• O centro de massa tem uma interpretação mais física e pode ser pensado em termos de extensão: = ( ÿ 1)/2.
Você também pode especificar a meia-vida em termos de uma unidade conversível timedelta para especificar a quantidade de tempo que leva
para uma observação cair para metade do seu valor ao especificar também uma sequência de tempos.
Em [74]: df
Fora[74]:
B
0 0,0
1 1,0
2 2,0
3NaN
4 4,0
B 0 0,000000 1
0,585786 2
1,523889 3
1,523889 4
3,233686
A fórmula a seguir é usada para calcular a média ponderada exponencialmente com um vetor de entrada de tempos:
-
0,5
= ÿÿ =0
-
- ,
ÿÿ =0 0,5
ExponentialMovingWindow também possui um argumento ignore_na, que determina como os valores nulos intermediários afetam o
cálculo dos pesos. Quando ignore_na=False (o padrão), os pesos são calculados com base em posições absolutas, de modo que
valores nulos intermediários afetem o resultado. Quando ignore_na=True, os pesos são calculados ignorando valores nulos
intermediários. Por exemplo, assumindo Adjust=True, se ignore_na=False, a média ponderada de 3, NaN, 5 seria calculada como
(1 ÿ ) (1 2 · 3 + 1 · 5
.
2 +1
ÿ)
(1 ÿ ) · 3 + 1 · 5 (1
.
ÿ)+1
As funções var(), std() e cov() possuem um argumento de polarização, especificando se o resultado deve conter estatísticas
tendenciosas ou imparciais. Por exemplo, se bias=True, ewmvar(x) é calculado como ewmvar(x) = ewma(x**2) - ewma(x)**2; enquanto
que se polarização=Falso (o padrão), as estatísticas de variância tendenciosa são dimensionadas por fatores de redução de polarização
(ÿÿÿ =0 )ÿ2 .
2
(ÿÿÿ =0 )ÿ2 ÿ ÿÿ =0
(Para = 1, isso se reduz ao fator /( ÿ1) usual, com = +1.) Consulte Variância ponderada da amostra na Wikipedia para obter
mais detalhes.
pandas contém amplos recursos e recursos para trabalhar com dados de série temporal para todos os domínios. Usando os
dtypes NumPy datetime64 e timedelta64, o pandas consolidou um grande número de recursos de outras bibliotecas Python,
como scikits.timeseries, bem como criou uma enorme quantidade de novas funcionalidades para manipular dados de séries
temporais.
Em [3]: dti
Saída[3]: DatetimeIndex(['2018-01-01', '2018-01-01', '2018-01-01'], dtype='datetime64[ns]', ÿÿ freq=None)
Em [5]: dti
Fora[5]:
DatetimeIndex(['2018-01-01 00:00:00', '2018-01-01 01:00:00', '2018-01-01
02:00:00'], dtype='datetime64[ns]
', frequência='H')
Em [7]: dti
Fora[7]:
(continua na próxima página)
Em [8]: dti.tz_convert("EUA/Pacífico")
Saída [8]:
DatetimeIndex (['2017-12-31 16:00:00-08:00', '2017-12-31 17:00:00-08:00', '2017-12-31 18: 00:00-08:00'],
dtype='datetime64[ns, EUA/Pacífico]',
freq='H')
Em [11]: ts
Saída[11]:
01-01-2018 00:00:00 0
01/01/2018 01:00:00 1
01/01/2018 02:00:00 2
01/01/2018 03:00:00 3
01/01/2018 04:00:00 4
Freq: H, tipo d: int64
Em [12]: ts.resample("2H").mean()
Fora[12]:
01/01/2018 00:00:00 0,5
01-01-2018 02:00:00 2.5 01-01-2018
04:00:00 4.0 Freq: 2H, tipo d: float64
Em [14]: sexta-feira.day_name()
Saída[14]: 'Sexta-feira'
# Adicionar 1 dia
em [15]: sábado = sexta + pd.Timedelta("1 dia")
Em [16]: sábado.day_name()
Saída[16]: 'Sábado'
Em [18]: monday.day_name()
Saída[18]: 'Segunda-feira'
O pandas fornece um conjunto de ferramentas relativamente compacto e independente para executar as tarefas acima e muito mais.
1. Data e hora: uma data e hora específicas com suporte de fuso horário. Semelhante a datetime.datetime do padrão
biblioteca.
2. Deltas de tempo: uma duração de tempo absoluta. Semelhante a datetime.timedelta da biblioteca padrão.
3. Intervalos de tempo: Um período de tempo definido por um ponto no tempo e sua frequência associada.
4. Deslocamentos de data: Uma duração relativa que respeita a aritmética do calendário. Semelhante a dateutil.relativedelta.
relativodelta do pacote dateutil.
Conceito Escalar Classe de matriz tipo de dados pandas Método de Criação Primária
Aula
Data Carimbo de data/hora DatetimeIndex datetime64[ns] ou até_datahora ou intervalo_de_datas
vezes datetime64[ns, tz]
Tempo Timedelta TimedeltaIndextimedelta64[ns] to_timedelta ou
deltas timedelta_range
Tempo Período PeríodoÍndice período[freq] Período ou intervalo_período
vãos
Data de folga- DataOffset Nenhum Nenhum DataOffset
conjuntos
Para dados de série temporal, é convencional representar o componente temporal no índice de uma Série ou DataFrame para que
manipulações podem ser realizadas em relação ao elemento de tempo.
No entanto, Series e DataFrame também podem suportar diretamente o componente de tempo como os próprios dados.
Series e DataFrame estenderam o suporte e a funcionalidade de tipos de dados para datetime, timedelta e Period
dados quando passados para esses construtores. Os dados DateOffset, entretanto, serão armazenados como dados de objeto.
dtype: objeto
Por último, pandas representa datas nulas, deltas de tempo e intervalos de tempo como NaT, o que é útil para representar valores semelhantes a
datas nulas ou ausentes e se comporta de maneira semelhante a np.nan para dados flutuantes.
Em [24]: pd.Timestamp(pd.NaT)
Fora[24]: NaT
Em [25]: pd.Timedelta(pd.NaT)
Fora[25]: NaT
Em [26]: pd.Period(pd.NaT)
Fora[26]: NaT
Os dados com carimbo de data e hora são o tipo mais básico de dados de série temporal que associam valores a pontos no tempo. Para
objetos pandas, significa usar os pontos no tempo.
Em [29]: pd.Timestamp("01/05/2012")
Saída[29]: Carimbo de data/hora('2012-05-01 00:00:00')
Em [30]: pd.Timestamp(2012, 5, 1)
Saída[30]: Carimbo de data/hora('2012-05-01 00:00:00')
No entanto, em muitos casos, é mais natural associar coisas como variáveis de mudança a um intervalo de tempo. O intervalo representado
por Período pode ser especificado explicitamente ou inferido a partir do formato de string de data e hora.
Por exemplo:
Em [31]: pd.Period("2011-01")
Fora[31]: Período('2011-01', 'M')
Timestamp e Period podem servir como índice. Listas de carimbo de data/hora e período são automaticamente coagidas
para DatetimeIndex e PeriodIndex respectivamente.
Em [33]: datas =
....: [ pd.Timestamp("2012-05-01"),
....: pd.Timestamp("2012-05-02"),
....: pd.Timestamp("2012-05-03"),
....: ]
....:
Em [35]: tipo(ts.index)
Saída[35]: pandas.core.indexes.datetimes.DatetimeIndex
Em [37]: ts
Saída[37]:
01/05/2012 0,469112
02/05/2012 -0,282863
03-05-2012 -1.509059
tipo d: float64
Em [40]: tipo(ts.index)
Fora[40]: pandas.core.indexes.period.PeriodIndex
Entrada [42]: ts
Saída [42]:
2012-01 -1,135632 2012-02
1,212112 2012-03 -0,173215
Freq: M, dtype: float64
pandas permite capturar ambas as representações e converter entre elas. Nos bastidores, o pandas representa carimbos de data/
hora usando instâncias de Timestamp e sequências de carimbos de data/hora usando instâncias de DatetimeIndex. Para
intervalos de tempo regulares, o pandas usa objetos Period para valores escalares e PeriodIndex para sequências de intervalos.
Melhor suporte para intervalos irregulares com pontos iniciais e finais arbitrários estará disponível em versões futuras.
Para converter uma série ou objeto semelhante a uma lista de objetos semelhantes a datas, por exemplo, strings, épocas ou uma
mistura, você pode usar a função to_datetime. Quando passado por uma Série, retorna uma Série (com o mesmo índice), enquanto
uma lista é convertida em um DatetimeIndex:
Se você usar datas que começam com o dia primeiro (ou seja, no estilo europeu), você pode passar a bandeira dayfirst:
Aviso: você vê no exemplo acima que dayfirst não é rigoroso. Se uma data não puder ser analisada com o primeiro dia, ela
será analisada como se dayfirst fosse False e, no caso de análise de strings de datas delimitadas (por exemplo, 31-12-2012),
um aviso também será gerado.
Se você passar uma única string para to_datetime, ela retornará um único carimbo de data/hora. Timestamp também pode aceitar
entrada de string, mas não aceita opções de análise de string como dayfirst ou format, então use to_datetime se forem necessários.
Em [47]: pd.to_datetime("2010/11/12")
Saída[47]: Carimbo de data/hora('2010-11-12 00:00:00')
Em [48]: pd.Timestamp("2010/11/12")
Saída[48]: Carimbo de data/hora('2010-11-12 00:00:00')
A string 'infer' pode ser passada para definir a frequência do índice como a frequência inferida na criação:
Além da sequência de data e hora necessária, um argumento de formato pode ser passado para garantir uma análise específica.
Isso também poderia acelerar consideravelmente a conversão.
Para obter mais informações sobre as opções disponíveis ao especificar a opção de formato, consulte a documentação de data e hora do
Python.
Você também pode passar um DataFrame de colunas inteiras ou de string para montar em uma série de carimbos de data/hora.
Em [54]: pd.to_datetime(df)
Saída [54]:
0 04/02/2015 02:00:00 1 05/03/2016
03:00:00 dtype: datetime64[ns]
pd.to_datetime procura designações padrão do componente datetime nos nomes das colunas, incluindo:
Dados inválidos
Passe erros='ignore' para retornar a entrada original quando não for analisável:
Passe errors='coerce' para converter dados não analisáveis em NaT (não um horário):
pandas suporta a conversão de tempos de época inteiros ou flutuantes para Timestamp e DatetimeIndex. A unidade padrão é
nanossegundos, pois é assim que os objetos Timestamp são armazenados internamente. No entanto, as épocas são frequentemente
armazenadas em outra unidade que pode ser especificada. Eles são calculados a partir do ponto inicial especificado pelo parâmetro origin.
Em [58]: pd.to_datetime(
....: [1349720105, 1349806505, 1349892905, 1349979305, 1350065705], unidade = "s"
....: )
....:
Fora[58]:
DatetimeIndex(['2012-10-08 18:15:05', '2012-10-09 18:15:05', '2012-10-10 18:15:05',
'2012-10-11 18: 15:05', '12/10/2012 18:15:05'],
dtype='datetime64[ns]',freq=Nenhum)
Em [59]: pd.to_datetime(
....: [1349720105100, 1349720105200 , 1349720105300, 1349720105400, 1349720105500], unidade = "ms",
....:
....: )
....:
Saída [59]:
DatetimeIndex (['2012-10-08 18:15:05.100000', '2012-10-08 18:15:05.200000', '2012-10-08
18:15:05.300000', '2012- 08/10 18:15:05.400000', '08/10/2012 18:15:05.500000'],
dtype='datetime64[ns]', freq=Nenhum)
Nota: O parâmetro unit não usa as mesmas strings que o parâmetro format discutido acima). As unidades disponíveis estão
listadas na documentação de pandas.to_datetime().
Em [60]: pd.Timestamp(1262347200000000000).tz_localize("EUA/Pacífico")
Saída[60]: Timestamp('2010-01-01 12:00:00-0800', tz='EUA/Pacífico')
Em [61]: pd.DatetimeIndex([1262347200000000000]).tz_localize("EUA/Pacífico")
Out[61]: DatetimeIndex(['2010-01-01 12:00:00-08:00'], dtype='datetime64[ns, US/Pacific]', ÿÿ freq=None)
Nota: Os tempos das épocas serão arredondados para o nanossegundo mais próximo.
Aviso: A conversão de tempos de época flutuante pode levar a resultados imprecisos e inesperados. Os carros flutuantes do Python têm
precisão de cerca de 15 dígitos em decimal. O arredondamento durante a conversão de float para carimbo de data/hora de alta precisão é inevitável.
A única maneira de obter precisão exata é usar tipos de largura fixa (por exemplo, um int64).
Veja também:
Para inverter a operação acima, ou seja, para converter de um Timestamp para uma época 'unix':
Em [65]: selos
Fora[65]:
DatetimeIndex(['2012-10-08 18:15:05', '2012-10-09 18:15:05', '2012-10-10 18:15:05',
'2012-10-11 18: 15:05'], dtype='datetime64[ns]', freq='D')
Subtraímos a época (meia-noite de 1º de janeiro de 1970 UTC) e depois dividimos o piso pela “unidade” (1 segundo).
Usando o parâmetro origin, pode-se especificar um ponto de partida alternativo para a criação de um DatetimeIndex. Por exemplo,
para usar 1960-01-01 como data de início:
O padrão é definido em origin='unix', cujo padrão é 1970-01-01 00:00:00. Comumente chamada de 'época unix' ou hora POSIX.
Para gerar um índice com carimbos de data e hora, você pode usar o construtor DatetimeIndex ou Index e passar uma lista de
objetos de data e hora:
Em [69]: datas =
....: [ datetime.datetime(2012, 5, 1),
....: datetime.datetime(2012, 5, 2),
....: datetime.datetime(2012, 5, 3),
....: ]
....:
Em [71]: índice
Out[71]: DatetimeIndex(['2012-05-01', '2012-05-02', '2012-05-03'], dtype='datetime64[ns] ÿÿ', freq=None)
Em [73]: índice
Out[73]: DatetimeIndex(['2012-05-01', '2012-05-02', '2012-05-03'], dtype='datetime64[ns] ÿÿ', freq=None)
Na prática, isso se torna muito complicado porque muitas vezes precisamos de um índice muito longo com um grande número de carimbos de data/hora.
Se precisarmos de carimbos de data/hora em uma frequência regular, podemos usar as funções date_range() e bdate_range()
para criar um DatetimeIndex. A frequência padrão para intervalo_data é um dia corrido , enquanto o padrão para intervalo_data
é um dia útil:
Em [77]: índice
Fora[77]:
DatetimeIndex(['2011-01-01', '2011-01-02', '2011-01-03', '2011-01-04', '2011-01-05', '2011-01-06' ,
'2011-01-07', '2011-01-08', '2011-01-09', '2011-01-10',
...
'2011-12-23', '2011-12-24', '2011-12-25', '2011-12-26', '2011-12-27',
'2011-12-28', '2011 -12-29', '2011-12-30', '2011-12-31', '2012-01-01'],
dtype='datetime64[ns]',
comprimento=366, freq='D')
Em [79]: índice
Fora[79]:
DatetimeIndex(['2011-01-03', '2011-01-04', '2011-01-05', '2011-01-06', '2011-01-07', '2011-01-10' ,
'11/01/2011', '12/01/2011',
(continua na próxima página)
'13/01/2011', '14/01/2011',
...
'2011-12-19', '2011-12-20', '2011-12-21', '2011-12-22', '2011-12-23',
'2011-12-26', '2011 -12-27', '2011-12-28', '2011-12-29', '2011-12-30'],
dtype='datetime64[ns]',
comprimento=260, freq='B')
Funções de conveniência como date_range e bdate_range podem utilizar uma variedade de aliases de frequência:
...
'2093-07-31', '2093-08-31', '2093-09-30', '2093-10-31', '2093-11-30',
'2093-12-31', '2094 -01-31', '2094-02-28', '2094-03-31', '2094-04-30'],
...
'2071-01-01', '2071-04-01', '2071-07-01', '2071-10-01', '2072-01-01',
'2072-04-01', '2072 -07-01', '2072-10-03', '2073-01-02', '2073-04-03'],
date_range e bdate_range facilitam a geração de um intervalo de datas usando várias combinações de parâmetros como
início, fim, períodos e frequência. As datas de início e término são estritamente inclusivas, portanto não serão geradas
datas fora das especificadas:
dtype='datetime64[ns]', freq='W-SUN')
dtype='datetime64[ns]',freq='B')
dtype='datetime64[ns]',freq='B')
A especificação de início, fim e períodos gerará um intervalo de datas com espaçamento uniforme do início ao fim, inclusive,
com períodos e números de elementos no DatetimeIndex resultante:
dtype='datetime64[ns]',freq=Nenhum)
bdate_range também pode gerar um intervalo de datas de frequência personalizadas usando os parâmetros weekmask e feriados.
Esses parâmetros só serão usados se uma sequência de frequência personalizada for passada.
...
'2011-12-09', '2011-12-12', '2011-12-14', '2011-12-16', '2011-12-19', '2011-12-21',
'2011 -12-23', '2011-12-26', '2011-12-28', '2011-12-30'], dtype='datetime64[ns]',
comprimento=154, freq='C')
dtype='datetime64[ns]', freq='CBMS')
Veja também:
Como o pandas representa carimbos de data/hora em resolução de nanossegundos, o intervalo de tempo que pode ser representado usando um número
inteiro de 64 bits é limitado a aproximadamente 584 anos:
Veja também:
2.20.6 Indexação
Um dos principais usos do DatetimeIndex é como índice para objetos pandas. A classe DatetimeIndex contém muitas otimizações relacionadas
a séries temporais:
• Uma grande variedade de datas para vários deslocamentos são pré-calculadas e armazenadas em cache para tornar a geração
intervalos de datas subsequentes muito rápido (basta pegar uma fatia).
• A união de objetos DatetimeIndex sobrepostos com a mesma frequência é muito rápida (importante para dados rápidos
alinhamento).
• Acesso rápido aos campos de data através de propriedades como ano, mês, etc.
Os objetos DatetimeIndex têm todas as funcionalidades básicas dos objetos Index regulares e uma miscelânea de métodos avançados
específicos de séries temporais para fácil processamento de frequência.
Veja também:
Métodos de reindexação
Nota: Embora o pandas não force você a ter um índice de data classificado, alguns desses métodos podem ter um comportamento inesperado
ou incorreto se as datas não estiverem classificadas.
DatetimeIndex pode ser usado como um índice normal e oferece todas as suas funcionalidades inteligentes, como seleção, fatiamento, etc.
dtype='datetime64[ns]',freq='BM')
Datas e strings analisadas para carimbos de data/hora podem ser passadas como parâmetros de indexação:
Em [99]: ts["31/01/2011"]
Fora[99]: 0,11920871129693428
Em [101]: ts["31/10/2011":"31/12/2011"]
Fora[101]:
31/10/2011 0,271860
30/11/2011 -0,424972
30/12/2011 0,567020
Freq: BM, tipo d: float64
Para facilitar o acesso a séries temporais mais longas, você também pode passar o ano ou o ano e o mês como strings:
Em [102]: ts["2011"]
Fora[102]:
31/01/2011 0,119209
28/02/2011 -1.044236
31/03/2011 -0,861849
29/04/2011 -2.104569
31/05/2011 -0,494929
30/06/2011 1.071804
29/07/2011 0,721555
31/08/2011 -0,706771
30/09/2011 -1,039575
31/10/2011 0,271860
30/11/2011 -0,424972
30/12/2011 0,567020
Freq: BM, tipo d: float64
Em [103]: ts["2011-6"]
Fora[103]:
30/06/2011 1.071804
Freq: BM, tipo d: float64
Este tipo de fatiamento também funcionará em um DataFrame com DatetimeIndex. Como a seleção parcial de strings é uma
forma de fatiamento de rótulo, os pontos finais serão incluídos. Isso incluiria horários correspondentes em uma data incluída:
Aviso: a indexação de linhas do DataFrame com uma única string com getitem (por exemplo, frame[dtstring]) está obsoleta
começando com pandas 1.2.0 (dada a ambigüidade se está indexando as linhas ou selecionando uma coluna) e será
removido em uma versão futura. O equivalente com .loc (por exemplo, frame.loc[dtstring]) ainda é suportado.
Em [105]: dft
Fora[105]:
A
01/01/2013 00:00:00 0,276232
01-01-2013 00:01:00 -1.087401
01-01-2013 00:02:00 -0,673690
01/01/2013 00:03:00 0,113648 01/01/2013
00:04:00 -1,478427
... ...
2013-03-11 10:35:00 -0.747967 2013-03-11
10:36:00 -0.034523 2013-03-11 10:37:00
-0.201754 2013-03-11 10:38:00 -1.509067
20134 03-11 10:39:00 -1.693043
Em [106]: dft.loc["2013"]
Fora[106]:
A
01/01/2013 00:00:00 0,276232
01-01-2013 00:01:00 -1.087401
01-01-2013 00:02:00 -0,673690
01/01/2013 00:03:00 0,113648
01-01-2013 00:04:00 -1.478427
... ...
11/03/2013 10:35:00 -0,747967
11/03/2013 10:36:00 -0,034523
11/03/2013 10:37:00 -0,201754
11/03/2013 10:38:00 -1,509067 11/03/2013
10:39:00 -1,693043
Isso começa na primeira vez no mês e inclui a última data e hora do mês:
Em [107]: dft["2013-1":"2013-2"]
Fora[107]:
A
01/01/2013 00:00:00 0,276232
01-01-2013 00:01:00 -1.087401
01-01-2013 00:02:00 -0,673690
01/01/2013 00:03:00 0,113648
01-01-2013 00:04:00 -1.478427
... ...
28/02/2013 23:55:00 0,850929
28/02/2013 23:56:00 0,976712
28/02/2013 23:57:00 -2.693884
(continua na próxima página)
Isso especifica um horário de parada que inclui todos os horários do último dia:
Em [108]: dft["2013-1":"2013-2-28"]
Fora[108]:
A
2013-01-01 00:00:00 0,276232 2013-01-01
00:01:00 -1,087401 2013-01-01 00:02:00
-0,673690 2013-01-01 00:03:00 0,113648
2013- 01- 01 00:04:00 -1,478427
... ...
2013-02-28 23:55:00 0,850929 2013-02-28
23:56:00 0,976712 2013-02-28 23:57:00
-2,693884 2013-02-28 23:58:00 -1,575535
2013- 02- 28 23:59:00 -1,573517
... ...
15/01/2013 12:26:00 0,371454
15/01/2013 12:27:00 -0,930806
15/01/2013 12:28:00 -0,069177
15/01/2013 12:29:00 0,066510
15/01/2013 12:30:00 -0,003945
Em [112]: dft2
Fora[112]:
A
01/01/2013 00:00:00 a -0,298694
b0,823553
01/01/2013 12:00:00 a 0,943285
b-1,479399
02/01/2013 00:00:00 a -1.643342
... ...
04/01/2013 12:00:00 b 0,069036 05/01/2013
00:00:00 a 0,122297 b 1,422060 05/01/2013
12:00:00 a
0,370079 b 1,016331
Em [113]: dft2.loc["05/01/2013"]
Fora[113]:
A
05/01/2013 00:00:00 a 0,122297
b 1,422060
05-01-2013 12:00:00 a 0,370079
b 1,016331
Em [118]: df
Fora[118]:
0 01-01-2019 00:00:00-08:00 0
A mesma string usada como parâmetro de indexação pode ser tratada como uma fatia ou como uma correspondência exata, dependendo
da resolução do índice. Se a string for menos precisa que o índice, ela será tratada como uma fatia, caso contrário, como uma
correspondência exata.
Uma string de carimbo de data/hora com menos precisão que um minuto fornece um objeto Series.
Uma string de carimbo de data/hora com resolução de minutos (ou mais precisa) fornece um escalar, ou seja, não é convertido em uma fatia.
Se a resolução do índice for a segunda, o carimbo de data/hora com precisão de minuto fornecerá uma série.
Se a string do carimbo de data/hora for tratada como uma fatia, ela também poderá ser usada para indexar DataFrame com .loc[].
Aviso: No entanto, se a string for tratada como uma correspondência exata, a seleção em [] do DataFrame será
em colunas e não em linhas, consulte Noções básicas de indexação. Por exemplo, dft_minuto['2011-12-31 23:59']
gerará KeyError, pois '2012-12-31 23:59' tem a mesma resolução do índice e não há coluna com esse nome:
Para sempre ter uma seleção inequívoca, seja a linha tratada como uma fatia ou como uma seleção única, use .loc.
Observe também que a resolução DatetimeIndex não pode ser menos precisa que dia.
Indexação exata
Conforme discutido na seção anterior, a indexação de um DatetimeIndex com uma string parcial depende da “precisão”
do período, ou seja, quão específico é o intervalo em relação à resolução do índice. Por outro lado, a indexação com
objetos Timestamp ou datetime é exata, porque os objetos têm significado exato. Eles também seguem a semântica de
incluir ambos os terminais.
Esses objetos Timestamp e datetime têm horas, minutos e segundos exatos, mesmo que não tenham sido
especificados explicitamente (são 0).
Sem padrões.
Em [135]:
.....: dft[ datetime.datetime(2013, 1, 1, 10, 12, 0): datetime.datetime( 2013, 2, 28, 10, 12, 0
.....:
.....: )
.....: ]
.....:
Fora[135]:
A
01/01/2013 10:12:00 0,565375
01/01/2013 10:13:00 0,068184
01/01/2013 10:14:00 0,788871
01/01/2013 10:15:00 -0,280343 01/01/2013
10:16:00 0,931536
... ...
(continua na próxima página)
É fornecida uma função de conveniência truncate() que é semelhante ao fatiamento. Observe que truncar assume um valor 0 para qualquer
componente de data não especificado em um DatetimeIndex em contraste com o fatiamento que retorna quaisquer datas parcialmente correspondentes:
Em [139]: ts2["2011-11":"2011-12"]
Saída[139]:
06/11/2011 0,437823
13/11/2011 -0,293083
20/11/2011 -0,059881
27/11/2011 1,252450
04/12/2011 0,046611
11/12/2011 0,059478
18/12/2011 -0,286539
25/12/2011 0,841669
Freq: W-SUN, tipo d: float64
Mesmo uma indexação sofisticada e complicada que quebra a regularidade de frequência do DatetimeIndex resultará em um
DatetimeIndex, embora a frequência seja perdida:
Existem várias propriedades de hora/data que podem ser acessadas a partir do Timestamp ou de uma coleção de carimbos de data/hora, como um
Índice de data e hora.
Propriedade Descrição
ano O ano da data e hora
mês O mês da data e hora
dia Os dias da data e hora
hora A hora da data e hora
minuto Os minutos da data e hora
segundo Os segundos da data e hora
data em Os microssegundos da data e hora
microssegundos Os nanossegundos da data e hora
em nanossegundos Retorna datetime.date (não contém informações de fuso horário)
tempo Retorna datetime.time (não contém informações de fuso horário)
horário Retorna datetime.time como hora local com informações de fuso horário
dia do ano O dia normal do ano
dia_do_ano O dia normal do ano
semana do O ordinal da semana do ano
ano O ordinal da semana do ano
semana dia O número do dia da semana com segunda=0, domingo=6
da semana O número do dia da semana com segunda=0, domingo=6
O número do dia da semana com segunda=0, domingo=6
Trimestre da data: janeiro-março = 1, abril-junho = 2, etc.
dia_da_semana O número de dias no mês da data e hora
dia da semana Indicação lógica se for primeiro dia do mês (definido por frequência)
trimestre Indicação lógica se for último dia do mês (definido por frequência)
dias_no_mês Indicação lógica se for primeiro dia do trimestre (definido por frequência)
é_mês_início Indicação lógica se for último dia do trimestre (definido por frequência)
é_mês_fim Indicação lógica se for primeiro dia do ano (definido por frequência)
é_quarto_início Indicação lógica se for último dia do ano (definido por frequência)
é_quarto_fim é_ano_inícioIndicação
é_ano_fimlógica
é_anosebissexto
a data pertence a um ano bissexto
Além disso, se você tiver uma série com valores semelhantes a data e hora, poderá acessar essas propriedades por meio do acessador .dt,
conforme detalhado na seção sobre acessadores .dt.
Você pode obter os componentes de ano, semana e dia do ano ISO da norma ISO 8601:
Em [142]: idx.isocalendar()
Fora[142]:
ano dia da semana
2019-12-29 2019 7 52
30/12/2019 2020 1 1
31/12/2019 2020 2 1
2020-01-01 2020 3 1
Em [143]: idx.to_series().dt.isocalendar()
Fora[143]:
(continua na próxima página)
Nos exemplos anteriores, sequências de frequência (por exemplo, 'D') foram usadas para especificar uma frequência que definia:
Essas sequências de frequência são mapeadas para um objeto DateOffset e suas subclasses. Um DateOffset é semelhante a um Timedelta que
representa uma duração de tempo, mas segue regras específicas de duração do calendário. Por exemplo, um dia Timedelta sempre
incrementará os horários em 24 horas, enquanto um dia DateOffset aumentará os horários para o mesmo horário no dia seguinte
se um dia representa 23, 24 ou 25 horas devido ao horário de verão. No entanto, todas as subclasses DateOffset que são
uma hora ou menos (Hora, Minuto, Segundo, Mili, Micro, Nano) comportam-se como Timedelta e respeitam o tempo absoluto.
O DateOffset básico atua de forma semelhante a dateutil.relativedelta (documentação relativadelta) que muda uma data
tempo pela duração do calendário correspondente especificada. O operador aritmético (+) pode ser usado para realizar a mudança.
Em [148]: sexta-feira.nome_dia()
Saiu[148]: 'Sexta-feira'
A maioria dos DateOffsets possui strings de frequências associadas, ou aliases de deslocamento, que podem ser passados para argumentos de palavras-chave
freq. As compensações de data disponíveis e as sequências de frequência associadas podem ser encontradas abaixo:
DateOffsets também possuem métodos rollforward() e rollback() para avançar ou retroceder uma data
respectivamente, para uma data de compensação válida relativa à compensação. Por exemplo, as compensações comerciais rolarão datas que chegarão ao
fins de semana (sábado e domingo) para segunda-feira, uma vez que as compensações comerciais operam durante a semana.
Em [153]: ts.day_name()
Fora[153]: 'Sábado'
# A data é trazida primeiro para a data de deslocamento mais próxima e depois a hora é adicionada
Em [156]: ts + deslocamento
Saída[156]: Carimbo de data/hora('2018-01-08 10:00:00')
Essas operações preservam informações de tempo (hora, minuto, etc.) por padrão. Para redefinir o horário para meia-noite, use
normalize() antes ou depois de aplicar a operação (dependendo se você deseja que as informações de horário sejam incluídas na operação).
Em [159]: dia + ts
Saída[159]: Carimbo de data/hora('2014-01-02 09:00:00')
Em [163]: hora + ts
Saída[163]: Carimbo de data/hora('2014-01-01 23:00:00')
Deslocamentos paramétricos
Alguns dos deslocamentos podem ser “parametrizados” quando criados para resultar em comportamentos diferentes. Por exemplo, o
deslocamento semanal para gerar dados semanais aceita um parâmetro de dia da semana que resulta nas datas geradas sempre em
um determinado dia da semana:
Entrada [167]:
d Saída [167]: datetime.datetime(2008, 8, 18, 9, 0)
Em [168]: d + pd.offsets.Week()
Saída[168]: Carimbo de data/hora('2008-08-25 09:00:00')
Em [170]: (d + pd.offsets.Week(weekday=4)).weekday()
Fora[170]: 4
Em [171]: d - pd.offsets.Week()
Saída[171]: Carimbo de data/hora('2008-08-11 09:00:00')
Em [172]: d + pd.offsets.Week(normalize=True)
Saída[172]: Carimbo de data/hora('2008-08-25 00:00:00')
Em [173]: d - pd.offsets.Week(normalize=True)
Saída[173]: Carimbo de data/hora('2008-08-11 00:00:00')
Em [174]: d + pd.offsets.YearEnd()
Saída[174]: Carimbo de data/hora('2008-12-31 09:00:00')
Em [175]: d + pd.offsets.YearEnd(mês=6)
Saída[175]: Carimbo de data/hora('2009-06-30 09:00:00')
Os deslocamentos podem ser usados com Series ou DatetimeIndex para aplicar o deslocamento a cada elemento.
Em [177]: s = pd.Series(rng)
Em [178]: anel
Out[178]: DatetimeIndex(['2012-01-01', '2012-01-02', '2012-01-03'], dtype='datetime64[ns] ÿÿ', freq='D')
Em [180]: s + pd.DateOffset(meses=2)
Fora[180]:
0 01/03/2012
12012-03-02
2012-03-03
tipo d: datahora64[ns]
Em [181]: s - pd.DateOffset(meses=2)
Fora[181]:
0 01-11-2011
12011-11-02
2 03/11/2011
tipo d: datahora64[ns]
Se a classe de deslocamento for mapeada diretamente para um Timedelta (Dia, Hora, Minuto, Segundo, Micro, Mili, Nano), ela poderá ser usada
exatamente como um Timedelta - consulte a seção Timedelta para obter mais exemplos.
Em [182]: s - pd.offsets.Day(2)
Fora[182]:
0 30/12/2011
131-12-2011
2012-01-01
tipo d: datahora64[ns]
Em [184]: td
Saída[184]:
0 3 dias 1 3
dias 2 3 dias
dtype:
timedelta64[ns]
Em [185]: td + pd.offsets.Minute(15)
Saída[185]:
0 3 dias 00:15:00 3 dias
1 00:15:00 3 dias
2 00:15:00 dtype:
timedelta64[ns]
Observe que alguns deslocamentos (como BQuarterEnd) não possuem uma implementação vetorizada. Eles ainda podem ser usados, mas
podem calcular significativamente mais lentamente e mostrarão um PerformanceWarning
A classe CDay ou CustomBusinessDay fornece uma classe paramétrica BusinessDay que pode ser usada para criar calendários
de dias úteis personalizados que levam em conta feriados locais e convenções locais de fim de semana.
Como exemplo interessante, vejamos o Egito, onde se observa um fim de semana de sexta a sábado.
.....: "01/05/2012",
.....: datahora.datehora(2013, 5, 1),
.....: np.datetime64("01/05/2014"),
.....: ]
.....:
Em [191]: dt + 2 * aniversário_egito
Saída[191]: Carimbo de data/hora('2013-05-05 00:00:00')
Os calendários de feriados podem ser usados para fornecer a lista de feriados. Consulte a seção do calendário de feriados para obter mais informações.
As compensações mensais que respeitam um determinado calendário de feriados podem ser definidas da forma habitual.
Em [200]: dt + bmth_us
(continua na próxima página)
dtype='datetime64[ns]', freq='CBMS')
Observação: a sequência de frequência 'C' é usada para indicar que um CustomBusinessDay DateOffset é usado. É importante
observar que, como CustomBusinessDay é um tipo parametrizado, as instâncias de CustomBusinessDay podem ser diferentes e isso
não é detectável na sequência de frequência 'C'. O usuário, portanto, precisa garantir que a sequência de frequência 'C' seja usada
consistentemente na aplicação do usuário.
Hora de negócios
A classe BusinessHour fornece uma representação do horário comercial no BusinessDay, permitindo utilizar horários de início e término
específicos.
Por padrão, o BusinessHour usa das 9h às 17h como horário comercial. Adicionar BusinessHour aumentará o Timestamp por frequência
horária. Se o carimbo de data/hora de destino estiver fora do horário comercial, vá para o próximo horário comercial e aumente-o.
Caso o resultado ultrapasse o término do horário comercial, as horas restantes serão somadas ao próximo dia útil.
Em [202]: bh = pd.offsets.BusinessHour()
Em [203]: bh
Saída[203]: <Horário Comercial: BH=09h00-17h00>
# 01/08/2014 é sexta-feira em
[204]: pd.Timestamp("01/08/2014 10:00").weekday()
Fora[204]: 4
# Se o resultado estiver no horário de término, passa para o próximo dia útil In [207]:
pd.Timestamp("2014-08-01 16:00") + bh Out[207]: Timestamp('2014-08-
04 09:00:00')
Você também pode especificar o horário de início e término por palavras-chave. O argumento deve ser uma str com uma representação
hora:minuto ou uma instância datetime.time. Especificar segundos, microssegundos e nanossegundos como horário comercial resulta
em ValueError.
Em [212]: bh
Saída[212]: <Horário Comercial: BH=11h00-20h00>
Passar o horário de início depois do final representa meia-noite no horário comercial. Nesse caso, o horário comercial ultrapassa a meia-
noite e se sobrepõe ao dia seguinte. O horário comercial válido é diferenciado pelo fato de ter começado em um BusinessDay válido.
Em [217]: bh
Saída[217]: <Horário Comercial: BH=17h00-09h00>
Aplicar BusinessHour.rollforward e rollback para resultados fora do horário comercial no início do próximo horário comercial ou
no final do dia anterior. Diferente de outras compensações, BusinessHour.rollforward pode gerar resultados diferentes de
Isso ocorre porque o término do horário comercial de um dia é igual ao início do horário comercial do dia seguinte. Por exemplo, no horário
comercial padrão (9h00 - 17h00), não há intervalo (0 minutos) entre 01/08/2014 às 17h e 04/08/2014 às 09h.
BusinessHour considera sábado e domingo feriados. Para usar feriados arbitrários, você pode usar o
deslocamento CustomBusinessHour, conforme explicado na subseção a seguir.
O CustomBusinessHour é uma mistura de BusinessHour e CustomBusinessDay que permite especificar feriados arbitrários. CustomBusinessHour
funciona da mesma forma que BusinessHour, exceto que ignora feriados personalizados especificados.
Em [230]: dt + bhour_us
Saída[230]: Carimbo de data/hora('2014-01-17 16:00:00')
Aliases de deslocamento
Vários apelidos de string são fornecidos para frequências úteis de séries temporais comuns. Iremos nos referir a esses aliases como deslocamento
apelido.
Alias Descrição
B frequência do dia útil
C frequência personalizada do dia útil
D frequência do dia de calendário
C frequência semanal
M frequência de final de mês
SM frequência final semestral (15º e final do mês)
BM frequência de final do mês comercial
CBM frequência de final do mês comercial personalizada
EM frequência de início do mês
SMS frequência de início semestral (1º e 15º)
BMS frequência de início do mês comercial
CBMS frequência de início do mês comercial personalizada
P frequência de final de trimestre
churrasco frequência de final do trimestre comercial
QS frequência de início do trimestre
BQS frequência de início do trimestre comercial
UMA, S frequência de final de ano
BEBÊ frequência de final de ano comercial
COMO, SIM frequência de início do ano
Frequência de início do ano comercial BAS, BYS
frequência do horário comercial
H
Frequência horária de BH
T, min frequência minuciosa
S segunda frequência
eu, senhora milissegundos
Você, nós microssegundos
N nanossegundos
Observação:
Ao usar os aliases de deslocamento acima, deve-se observar que funções como date_range(),
bdate_range(), retornará apenas timestamps que estejam no intervalo definido por start_date e
data final. Se start_date não corresponder à frequência, os timestamps retornados começarão
no próximo carimbo de data/hora válido, o mesmo para data_final, os carimbos de data/hora retornados irão parar no carimbo de data/hora válido anterior
carimbo de data/hora.
Por exemplo, para o deslocamento MS, se start_date não for o primeiro do mês, os carimbos de data/hora retornados começarão com
primeiro dia do mês seguinte. Se end_date não for o primeiro dia de um mês, o último carimbo de data/hora retornado será o primeiro
dia do mês correspondente.
Em [235]: datas_lst_1
Out[235]: DatetimeIndex(['2020-02-01', '2020-03-01', '2020-04-01'], dtype='datetime64[ns] ÿÿ', freq='MS')
Em [237]: datas_lst_2
Saída[237]: DatetimeIndex(['2020-01-01', '2020-02-01', '2020-03-01', '2020-04-01'], dtype= ÿÿ'datetime64[ns] ',
frequência='MS')
Podemos ver no exemplo acima date_range() e bdate_range() retornará apenas os carimbos de data e hora válidos entre
start_date e end_date. Se esses carimbos de data e hora não forem válidos para a frequência especificada, ele passará para o
próximo valor de data_inicial (respectivamente anterior para data_final)
Combinando apelidos
Como vimos anteriormente, o alias e a instância offset são fungíveis na maioria das funções:
dtype='datetime64[ns]', freq='86400000010U')
Deslocamentos ancorados
Alias Descrição
W-SUN W- frequência semanal (domingos). O mesmo que 'W'
MON frequência semanal (segundas-feiras)
Frequência semanal W-TUE (terças-feiras)
Eles podem ser usados como argumentos para date_range, bdate_range, construtores para DatetimeIndex, bem como várias outras funções
relacionadas a séries temporais em pandas.
Para as compensações ancoradas no início ou no final de uma frequência específica (MonthEnd, MonthBegin, WeekEnd, etc.), as regras a
seguir se aplicam ao avanço e retrocesso.
Quando n não for 0, se a data fornecida não estiver em um ponto de ancoragem, ela se moverá para o próximo ponto de ancoragem (anterior)
e moverá |n|-1 passos adicionais para frente ou para trás.
Se a data fornecida estiver em um ponto de ancoragem, ela será movida |n| aponta para frente ou para trás.
Para o caso em que n=0, a data não é movida se estiver em um ponto de ancoragem, caso contrário, ela é transferida para a próxima âncora
apontar.
Feriados/calendários de feriados
Feriados e calendários fornecem uma maneira simples de definir regras de feriados a serem usadas com CustomBusinessDay ou em outros
análise que requer um conjunto predefinido de feriados. A classe AbstractHolidayCalendar fornece todos os recursos necessários
métodos para retornar uma lista de feriados e apenas regras precisam ser definidas em uma classe específica de calendário de
feriados. Além disso, os atributos de classe start_date e end_date determinam em qual intervalo de datas os feriados são gerados. Esses
deve ser substituído na classe AbstractHolidayCalendar para que o intervalo seja aplicado a todas as subclasses do calendário.
USFederalHolidayCalendar é o único calendário que existe e serve principalmente como exemplo para o desenvolvimento de outros
calendários.
Para feriados que ocorrem em datas fixas (por exemplo, Memorial Day dos EUA ou 4 de julho), uma regra de observância determina quando
feriado é observado se cair em um fim de semana ou em algum outro dia não observado. As regras de observância definidas são:
Regra Descrição
next_workday muda de sábado para sexta e de domingo para segunda
sol- passar o domingo para a segunda-feira seguinte
dia_a_segunda
next_monday_or_tuesday mover sábado para segunda e domingo/segunda para terça
previous_sexta-feira move sábado e domingo para sexta-feira anterior”
next_monday move sábado e domingo para segunda-feira seguinte
..... :)
.....:
Em [262]: pd.date_range(
.....: start="01/07/2012", end="10/07/2012", freq=pd.offsets.CDay(calendar=cal)
.....: .to_pydatetime()
.....:
Fora[262]:
matriz([datahora.datahora(2012, 7, 2, 0, 0),
datahora.datehora(2012, 7, 3, 0, 0),
datetime.datetime(2012, 7, 5, 0, 0),
datahora.datehora(2012, 7, 6, 0, 0),
datahora.datehora(2012, 7, 9, 0, 0),
datetime.datetime(2012, 7, 10, 0, 0)], dtype=objeto)
Os intervalos são definidos pelos atributos de classe start_date e end_date de AbstractHolidayCalendar. Os padrões são
mostrados abaixo.
Em [272]: cal.feriados()
Out[272]: DatetimeIndex(['2012-05-28', '2012-07-04', '2012-10-08'], dtype='datetime64[ns] ÿÿ', freq=None)
Cada classe de calendário é acessível por nome usando a função get_calendar que retorna uma instância da classe holiday.
Qualquer classe de calendário importada estará automaticamente disponível por esta função. Além disso, HolidayCalendarFactory
fornece uma interface fácil para criar calendários que são combinações de calendários ou calendários com regras adicionais.
Mudança / atraso
Pode-se querer deslocar ou atrasar os valores em uma série temporal para frente e para trás no tempo. O método para isso é shift(),
que está disponível em todos os objetos pandas.
Em [279]: ts = ts[:5]
Em [280]: ts.shift(1)
Fora[280]:
01/01/2012 NaN
02/01/2012 0,0
03/01/2012 1,0
Freq: D, tipo d: float64
O método shift aceita um argumento freq que pode aceitar uma classe DateOffset ou outro objeto do tipo timedelta
ou também um alias de deslocamento.
Quando freq é especificado, o método shift altera todas as datas no índice em vez de alterar o alinhamento do
dados e o índice:
Observe que quando freq é especificado, a entrada inicial não é mais NaN porque os dados não estão sendo realinhados.
Conversão de frequência
A principal função para alterar frequências é o método asfreq() . Para um DatetimeIndex, isso é basicamente apenas
um wrapper fino, mas conveniente em torno de reindex() que gera um intervalo de datas e chama reindex.
Em [286]: ts
Fora[286]:
01/01/2010 1.494522
06-01-2010 -0,778425
11/01/2010 -0,253355
Freq: 3B, tipo d: float64
Em [287]: ts.asfreq(pd.offsets.BDay())
Fora[287]:
01-01-2010 1.494522
04-01-2010 NaN
05-01-2010 NaN
06-01-2010 -0,778425
07/01/2010 NaN
08/01/2010 NaN
11/01/2010 -0,253355
Freq: B, tipo d: float64
asfreq fornece uma conveniência adicional para que você possa especificar um método de interpolação para quaisquer lacunas que possam aparecer após
a conversão de frequência.
Relacionado a asfreq e reindex está fillna(), que está documentado na seção de dados ausentes.
DatetimeIndex pode ser convertido em uma matriz de objetos datetime.datetime nativos do Python usando o método to_pydatetime.
2.20.10 Reamostragem
O pandas possui uma funcionalidade simples, poderosa e eficiente para realizar operações de reamostragem durante a conversão de
frequência (por exemplo, converter dados secundários em dados de 5 minutos). Isso é extremamente comum, mas não se limita a,
aplicações financeiras.
resample() é um groupby baseado em tempo, seguido por um método de redução em cada um de seus grupos. Veja alguns exemplos de livros
de receitas para algumas estratégias avançadas.
O método resample() pode ser usado diretamente dos objetos DataFrameGroupBy, consulte a documentação groupby.
Fundamentos
Em [291]: ts.resample("5Min").sum()
Saída [291]:
01/01/2012 25103 Freq: 5T,
dtype: int64
A função de reamostragem é muito flexível e permite especificar muitos parâmetros diferentes para controlar a conversão de frequência
e a operação de reamostragem.
Qualquer função disponível via despacho está disponível como um método do objeto retornado, incluindo soma, média, padrão, sem,
máximo, mínimo, mediana, primeiro, último, ohlc:
Em [292]: ts.resample("5Min").mean()
Fora[292]:
01/01/2012 251.03
Freq: 5T, tipo d: float64
Em [293]: ts.resample("5Min").ohlc()
Fora[293]:
abrir alto baixo fechar 205
01/01/2012 308 460 9
Em [294]: ts.resample("5Min").max()
Saída [294]:
01/01/2012 460 Freq: 5T,
dtype: int64
Para redução da resolução, fechado pode ser definido como 'esquerda' ou 'direita' para especificar qual final do intervalo é fechado:
Parâmetros como rótulo são usados para manipular os rótulos resultantes. label especifica se o resultado é rotulado com
o início ou o fim do intervalo.
Aviso: Os valores padrão para rótulo e fechado são 'esquerdo' para todos os deslocamentos de frequência, exceto 'M', 'A', 'Q',
'BM', 'BA', 'BQ' e 'W', todos com o padrão 'certo'.
Isso pode levar involuntariamente a uma previsão futura, em que o valor de um momento posterior é retrocedido para um momento anterior, pois
no exemplo a seguir com a frequência BusinessDay :
Em [301]: s.dt.day_name()
Fora[301]:
01/01/2000 Sábado
02/01/2000 Domingo
03/01/2000 NaN
04-01-2000 Terça-feira
05/01/2000 Quarta-feira
Freq: D, dtype: objeto
Observe como o valor do domingo foi reduzido para a sexta-feira anterior. Para obter o comportamento onde o valor para
O parâmetro axis pode ser definido como 0 ou 1 e permite reamostrar o eixo especificado para um DataFrame.
kind pode ser definido como 'timestamp' ou 'period' para converter o índice resultante de/para representações de timestamp e intervalo de
tempo. Por padrão, a reamostragem mantém a representação de entrada.
a convenção pode ser definida como 'início' ou 'fim' ao reamostrar os dados do período (detalhe abaixo). Ele especifica quão baixa frequência
períodos são convertidos em períodos de frequência mais alta.
Aumento da resolução
Para upsampling, você pode especificar uma forma de upsample e o parâmetro limite para interpolar sobre as lacunas que são
criada:
Em [305]: ts[:2].resample("250L").ffill()
Fora[305]:
01/01/2012 00:00:00.000 308
01-01-2012 00:00:00.250 308
01-01-2012 00:00:00.500 308
01-01-2012 00:00:00.750 308
01/01/2012 00:00:01.000 Freq: 204
250L, dtype: int64
Em [306]: ts[:2].resample("250L").ffill(limit=2)
Fora[306]:
01-01-2012 00:00:00.000 308,0
01-01-2012 00:00:00.250 308,0
01-01-2012 00:00:00.500 308,0
01-012012 00:00:00.750 NaN
01-01-2012 00:00:01.000 Freq: 204,0
250L, tipo d: float64
Reamostragem esparsa
Séries temporais esparsas são aquelas em que você tem muito menos pontos em relação à quantidade de tempo que deseja
redimensionamento. Aumentar a resolução ingenuamente de uma série esparsa pode potencialmente gerar muitos valores intermediários. Quando você não
Se você quiser usar um método para preencher esses valores, por exemplo, fill_method é None, então os valores intermediários serão preenchidos com NaN.
Como a reamostragem é um agrupamento baseado no tempo, a seguir está um método para reamostrar com eficiência apenas os grupos que não são
tudo NaN.
Em [309]: ts.resample("3T").sum()
Fora[309]:
01-01-2014 00:00:00 0
01-01-2014 00:03:00 0
01-01-2014 00:06:00 0
01-01-2014 00:09:00 0
01-01-2014 00:12:00 0
..
09/04/2014 23:48:00 0
09/04/2014 23:51:00 0
09/04/2014 23:54:00 0
09/04/2014 23:57:00 0
10/04/2014 00:00:00 99
Freq: 3T, Comprimento: 47521, tipo d: int64
Em vez disso, podemos reamostrar apenas os grupos onde temos pontos da seguinte forma:
Agregação
Semelhante à API de agregação, à API groupby e à API de janela, um Reamostrador pode ser reamostrado seletivamente.
Reamostrando um DataFrame, o padrão será atuar em todas as colunas com a mesma função.
Em [314]: df = pd.DataFrame(
.....: np.random.randn(1000, 3),
.....: índice=pd.date_range("01/01/2012", freq="S", períodos=1000),
.....: colunas=["A", "B", "C"],
..... :)
.....:
Em [315]: r = df.resample("3T")
Em [316]: r.mean()
Fora[316]:
A B C
01-01-2012 00:00:00 -0,033823 -0,121514 -0,081447
01-01-2012 00:03:00 0,056909 0,146731 -0,024320
01-01-2012 00:06:00 -0,058837 0,047046 -0,052021
01/01/2012 00:09:00 0,063123 -0,026158 -0,066533
01-01-2012 00:12:00 0,186340 -0,003144 0,074752
01-01-2012 00:15:00 -0,085954 -0,016287 -0,050046
Em [317]: r["A"].mean()
Fora[317]:
01-01-2012 00:00:00 -0,033823
01/01/2012 00:03:00 0,056909
01-01-2012 00:06:00 -0,058837
01-01-2012 00:09:00 0,063123
01-01-2012 00:12:00 0,186340
01-01-2012 00:15:00 -0,085954
Freq: 3T, Nome: A, tipo d: float64
Você pode passar uma lista ou ditado de funções para agregar, gerando um DataFrame:
Em um DataFrame reamostrado, você pode passar uma lista de funções para aplicar a cada coluna, o que produz um valor agregado
resultado com um índice hierárquico:
Ao passar um dict para agregar você pode aplicar uma agregação diferente às colunas de um DataFrame:
Os nomes das funções também podem ser strings. Para que uma string seja válida ela deve ser implementada no objeto reamostrado:
Além disso, você também pode especificar diversas funções de agregação para cada coluna separadamente.
Se um DataFrame não tiver um índice datetimelike, mas em vez disso você quiser fazer uma nova amostragem com base na coluna datetimelike no
quadro, ele poderá ser passado para a palavra-chave on.
Em [325]: df
Fora[325]:
namorar um
vd
1 04/01/2015 04/01/2015 0
2 11/01/2015 11/01/2015 1
3 18/01/2015 18/01/2015 2
4 25/01/2015 25/01/2015 3
5 01/02/2015 01/02/2015 4
Da mesma forma, se você quiser fazer uma nova amostragem por um nível semelhante a data e hora do MultiIndex, seu nome ou localização poderá ser
passado para a palavra-chave level.