1

I am trying to plot a financial contribution analysis, one bar chart with two vertical bars, one representing a portfolio's gain contributed by equity and the other by Fixed Income (bonds) over a certain time period.

%matplotlib inline
import numpy as np
import pandas as pd
import itertools
import matplotlib.pyplot as plt
import matplotlib.ticker as ticker
import matplotlib.lines as mlines
import matplotlib.dates as mdates
import matplotlib.font_manager as fm
import matplotlib.patches as mpatches
import matplotlib.transforms as mtrans


d = {'col1': [0.006269, 0.003842, 0.002237, 0.001448, 0.000752, 0.000166]}
equity = pd.DataFrame(data=d, index=['Aktien Nordamerika', 'Gold', 'Aktien Flexibel', 'Aktien Europa', 'Aktien Schwellenlaender', 'Aktien Pazifik'])

d2 = {'col1': [0.009533, 0.003879, 0.001926, 0.000714]}
bonds = pd.DataFrame(data=d2, index=['Anleihen Investmentgrade', 'Hedgefonds', 'Hochzinsanleihen', 'Anleihen Schwellenlaender'])

The vertical bars starting at the x-axis should in sum represent the overall gain from ['equity','bonds‘] but be divided into by the index defined in the df.

I tried to do that by using the iterator building block itertools.zip_longest to assign the values of the incrementally gaining bar chart and then the color for each section.

fig, ax = plt.subplots()
fig.set_size_inches(4, 4.3)

bar_width = 0.26

x_values = np.array([0, 1.2])
x_pos = [list(x_values)]*2 + [x_values[0]]*4   

pl = [(p1,p2) if p2 is not None else p1 for p1, p2 in itertools.zip_longest(list(equity['col1'].values), list(bonds['col1'].values))]
colors = np.array((
                ['#FF7600', '#A9A9A9', '#1778A6', '#146189', '#5794B9', '#B0D2E7'],
                ['#004232', '#3AC2A0', '#007558', '#2A8C74']))
colormap = [(c1,c2) if c2 is not None else c1 for c1, c2 in itertools.zip_longest(colors[0],colors[1])]

then I would just use matplotlib's matplotlib.pyplot.bar(x, height, width=0.8, bottom=None, *, align='center', data=None, **kwargs) to create the desired bar chart..

for x, p, c in zip(x_pos, pl, colormap):
    ls_sub_aktien = plt.bar(x, p, align='edge', width=bar_width, linewidth=0.0001, color=c)

BUT the output does not give me the total division in the ['bonds'] bar, where only two of the row items are colored as defined...

The output I got with the missing 4 color split on the right bar: .jpg

Also, the left bar appears to include a color which should actually be found in the bar on the right hand side.

It would be amazing if you have had a similar issue and remember how you solved it, or if you have suggestion on how I could create this chart using a different approach. Sorry for my English and if anything is unclear let me know. Try it out, please. I'm wondering if you can solve it, thank you!

Mr. T
  • 11,960
  • 10
  • 32
  • 54
Petzii
  • 11
  • 2
  • Not looked into it in depth but get the depreciation warning: `VisibleDeprecationWarning: Creating an ndarray from ragged nested sequences (which is a list-or-tuple of lists-or-tuples-or ndarrays with different lengths or shapes) is deprecated. If you meant to do this, you must specify 'dtype=object' when creating the ndarray ['#004232', '#3AC2A0', '#007558', '#2A8C74']))`. Not the problem, I guess. But is there a reason to create this chart by hand instead of using pandas? – Mr. T Oct 26 '20 at 09:35
  • Here is an example of [how to plot stacked bars](https://stackoverflow.com/a/23428804/8881141) from a pandas dataframe. Probably easier to do the calculations in pandas (what it is designed for) and let matplotlib do the plotting (what it is designed for) than doing both things manually. – Mr. T Oct 26 '20 at 09:41

0 Answers0