darkpool
darkpool

Reputation: 14651

fill_between from a stacked dataframe

I have the following dataframe:

symbol       DAL        MS       QQQ       SPY      TLT  XLE
symbol                                                      
DAL          NaN       NaN       NaN       NaN      NaN  NaN
MS      0.560979       NaN       NaN       NaN      NaN  NaN
QQQ     0.621045  0.789771       NaN       NaN      NaN  NaN
SPY    -0.576444 -0.843485 -0.953304       NaN      NaN  NaN
TLT     0.186840  0.421957  0.333320 -0.347808      NaN  NaN
XLE     0.115093  0.578970  0.559711 -0.701126  0.38047  NaN

I then stack and order the dataframe and plot the result as a barchart as follows:

dfstacked = corr_df.stack().order()
dfstacked.plot(kind='bar')

symbol  symbol
SPY     QQQ      -0.953304
        MS       -0.843485
XLE     SPY      -0.701126
SPY     DAL      -0.576444
TLT     SPY      -0.347808
XLE     DAL       0.115093
TLT     DAL       0.186840
        QQQ       0.333320
XLE     TLT       0.380470
TLT     MS        0.421957
XLE     QQQ       0.559711
MS      DAL       0.560979
XLE     MS        0.578970
QQQ     DAL       0.621045
        MS        0.789771

enter image description here

What im trying to do now (without success) is to not plot this as a barchart but to instead plot it by filling in the area below and above zero. My guess is I should be using fill_between similar to these examples: link:

ax.fill_between(dfstacked.index, 0, dfstacked.values, where = dfstacked.values > 0, interpolate=True)
ax.fill_between(dfstacked.index, dfstacked.values, 0, where = dfstacked.values < 0, interpolate=True)

I get the error: TypeError: ufunc 'isfinite' not supported for the input types, and the inputs could not be safely coerced to any supported types according to the casting rule ''safe''

Upvotes: 4

Views: 725

Answers (3)

jezrael
jezrael

Reputation: 863166

You try reset_index:

dfstacked = dfstacked.reset_index(drop=True)
print dfstacked
0    -0.953304
1    -0.843485
2    -0.701126
3    -0.576444
4    -0.347808
5     0.115093
6     0.186840
7     0.333320
8     0.380470
9     0.421957
10    0.559711
11    0.560979
12    0.578970
13    0.621045
14    0.789771
dtype: float64

And then set axis x from multiindex:

import matplotlib.pyplot as plt
import matplotlib.ticker as ticker


dfstacked = corr_df.stack().order()

ticklabels = dfstacked.index.tolist()

dfstacked = dfstacked.reset_index(drop=True)
print dfstacked


ax = dfstacked.plot()

ax.fill_between(dfstacked.index, 0, dfstacked.values, where = dfstacked.values > 0, interpolate=True)
ax.fill_between(dfstacked.index, dfstacked.values, 0, where = dfstacked.values < 0, interpolate=True)
ax.xaxis.set_major_formatter(ticker.FixedFormatter(ticklabels))
plt.xticks(rotation=90)    
plt.show()

graph01

Upvotes: 4

Mel
Mel

Reputation: 6075

You can play with the width and edgecolor parameters of plt.bar to get something that look less like an histogram.

x=[1,2,3,4,5,6]
y=[-3,-1,5,3,4,2]

plt.bar(x,y,color='b',width=1,edgecolor="none")

enter image description here

Upvotes: 4

Sergey Antopolskiy
Sergey Antopolskiy

Reputation: 4300

Your syntax is a bit off. In your case fill_between needs X values, then value of Y to which you want to fill, and then your Y values.

Here is a little example:

import pandas as pd
import matplotlib.pyplot as plt
import numpy as np

s = pd.Series([-4,-3,-2,-1,0,1,2,3,4,5,6,7,8])
x = np.arange(len(s))
plt.fill_between(x,0,s)

area under curve

Then you can use your index to set_xticklabels.

Upvotes: 3

Related Questions