Como plotar colunas de um dataframe, como subplots
O que eu estou fazendo errado aqui? Desejo criar um novo dataframe dfe usar datas como o eixo x em um gráfico de linha para cada dataframe recém-criado (Emins, FTSE, Stoxx e Nikkei).
Eu tenho um dataframe chamado dfque criei de data.xlsx e se parece com isto:
Dates ES1 Z 1 VG1 NK1
0 2005-01-04 -0.0126 0.0077 -0.0030 0.0052
1 2005-01-05 -0.0065 -0.0057 0.0007 -0.0095
2 2005-01-06 0.0042 0.0017 0.0051 0.0044
3 2005-01-07 -0.0017 0.0061 0.0010 -0.0009
4 2005-01-11 -0.0065 -0.0040 -0.0147 0.0070
3670 2020-09-16 -0.0046 -0.0065 -0.0003 -0.0009
3671 2020-09-17 -0.0083 -0.0034 -0.0039 -0.0086
3672 2020-09-18 -0.0024 -0.0009 -0.0009 0.0052
3673 2020-09-23 -0.0206 0.0102 0.0022 -0.0013
3674 2020-09-24 0.0021 -0.0136 -0.0073 -0.0116
De dfeu criei 4 novos dataframes chamados Eminis, FTSE, Stoxx e Nikkei.
Obrigado pela ajuda!!!!
import numpy as np
import matplotlib.pyplot as plt
plt.style.use('classic')
df = pd.read_excel('data.xlsx')
df = df.rename(columns={'Dates':'Date','ES1': 'Eminis', 'Z 1': 'FTSE','VG1': 'Stoxx','NK1': 'Nikkei','TY1': 'Notes','G 1': 'Gilts', 'RX1': 'Bunds','JB1': 'JGBS','CL1': 'Oil','HG1': 'Copper','S 1': 'Soybeans','GC1': 'Gold','WILLTIPS': 'TIPS'})
headers = df.columns
Eminis = df[['Date','Eminis']]
FTSE = df[['Date','FTSE']]
Stoxx = df[['Date','Stoxx']]
Nikkei = df[['Date','Nikkei']]
# create multiple plots via plt.subplots(rows,columns)
fig, axes = plt.subplots(2,2, figsize=(20,15))
x = Date
y1 = Eminis
y2 = Notes
y3 = Stoxx
y4 = Nikkei
# one plot on each subplot
axes[0][0].line(x,y1)
axes[0][1].line(x,y2)
axes[1][0].line(x,y3)
axes[1][1].line(x,y4)
plt.legends()
plt.show()
Respostas
Uma solução elegante é:
- Defina a coluna Datas em seu DataFrame como o índice.
- Crie uma figura com o número necessário de subtramas (no seu caso 4), chamando plt.subplots .
- Desenhe um gráfico de seu DataFrame, passando:
- ax - o resultado de machados de subtramas (aqui é uma matriz de objetos Axes , não um único Axes ),
- subplots = True - para desenhar cada coluna em um subplot separado.
O código para fazer isso é:
fig, a = plt.subplots(2, 2, figsize=(12, 6), tight_layout=True)
df.plot(ax=a, subplots=True, rot=60);
Para testar o código acima, criei o seguinte DataFrame:
np.random.seed(1)
ind = pd.date_range('2005-01-01', '2006-12-31', freq='7D')
df = pd.DataFrame(np.random.rand(ind.size, 4),
index=ind, columns=['ES1', 'Z 1', 'VG1', 'NK1'])
e obtive a seguinte imagem:
Como meus dados de teste são aleatórios, eu assumi a frequência de "7 dias", para ter a imagem não muito "confusa". No caso de seus dados reais, considere, por exemplo, reamostrar com, por exemplo, também frequência '7D' e função de agregação média () .
- Acho que a opção mais sucinta é não fazer muitos dataframes, o que cria trabalho desnecessário e complexidade.
- Plotar dados é sobre como moldar o dataframe para a API de plotagem
- Nesse caso, a melhor opção é converter o dataframe para um formato longo (arrumado), de um formato largo, usando .stack.
- Isso coloca todos os rótulos em uma coluna e os valores em outra coluna
- Use seaborn.relplot, que pode criar um a FacetGridpartir de um dataframe em um formato longo.
seaborné uma API de alto nívelmatplotlibe torna a plotagem muito mais fácil.
- Se o dataframe contém muitas ações, mas apenas algumas devem ser plotadas, elas podem ser selecionadas com a indexação booleana
import pandas as pd
import seaborn as sns
import matplotlib.pyplot as plt
# import data from excel, or setup test dataframe
data = {'Dates': ['2005-01-04', '2005-01-05', '2005-01-06', '2005-01-07', '2005-01-11', '2020-09-16', '2020-09-17', '2020-09-18', '2020-09-23', '2020-09-24'],
'ES1': [-0.0126, -0.0065, 0.0042, -0.0017, -0.0065, -0.0046, -0.0083, -0.0024, -0.0206, 0.0021],
'Z 1': [0.0077, -0.0057, 0.0017, 0.0061, -0.004, -0.0065, -0.0034, -0.0009, 0.0102, -0.0136],
'VG1': [-0.003, 0.0007, 0.0051, 0.001, -0.0147, -0.0003, -0.0039, -0.0009, 0.0022, -0.0073],
'NK1': [0.0052, -0.0095, 0.0044, -0.0009, 0.007, -0.0009, -0.0086, 0.0052, -0.0013, -0.0116]}
df = pd.DataFrame(data)
# rename columns
df = df.rename(columns={'Dates':'Date','ES1': 'Eminis', 'Z 1': 'FTSE','VG1': 'Stoxx','NK1': 'Nikkei'})
# set Date to a datetime
df.Date = pd.to_datetime(df.Date)
# set Date as the index
df.set_index('Date', inplace=True)
# stack the dataframe
dfs = df.stack().reset_index().rename(columns={'level_1': 'Stock', 0: 'val'})
# to select only a subset of values from Stock, to plot, select them with Boolean indexing
df_select = dfs[dfs.Stock.isin(['Eminis', 'FTSE', 'Stoxx', 'Nikkei'])]`
# df_select.head()
Date Stock val
0 2005-01-04 Eminis -0.0126
1 2005-01-04 FTSE 0.0077
2 2005-01-04 Stoxx -0.0030
3 2005-01-04 Nikkei 0.0052
4 2005-01-05 Eminis -0.0065
# plot
sns.relplot(data=df_select, x='Date', y='val', col='Stock', col_wrap=2, kind='line')
O que eu estou fazendo errado aqui?
- A implementação atual é ineficiente, tem várias chamadas de método incorretas e variáveis indefinidas.
Datenão está definido parax = Datey2 = Notes:Notesnão está definido.linenão é umpltmétodo e causa umAttributeError; deveria serplt.ploty1 - y4são DataFrames, mas passados para o método plot para o eixo y, o que causaTypeError: unhashable type: 'numpy.ndarray'; uma coluna deve ser passada comoy..legendsnão é um método; Está.legend- A legenda deve ser exibida para cada subtrama, se uma for desejada.
Eminis = df[['Date','Eminis']]
FTSE = df[['Date','FTSE']]
Stoxx = df[['Date','Stoxx']]
Nikkei = df[['Date','Nikkei']]
# create multiple plots via plt.subplots(rows,columns)
fig, axes = plt.subplots(2,2, figsize=(20,15))
x = df.Date
y1 = Eminis.Eminis
y2 = FTSE.FTSE
y3 = Stoxx.Stoxx
y4 = Nikkei.Nikkei
# one plot on each subplot
axes[0][0].plot(x,y1, label='Eminis')
axes[0][0].legend()
axes[0][1].plot(x,y2, label='FTSE')
axes[0][1].legend()
axes[1][0].plot(x,y3, label='Stoxx')
axes[1][0].legend()
axes[1][1].plot(x,y4, label='Nikkei')
axes[1][1].legend()
plt.show()