Create a horizontal waterfall chart with python matplotlib - python

I am trying to create a waterfall chart, which is like a bar chart, except that each bar starts at the end of its neighboring bars, at the end or beginning, so you have the total, and can see how it breaks down.
I am trying to create this chart in python, but there are no direct charts in matplot.lib called waterfall.
I found code for a vertical waterfall, but I could not transform it to horizontal.
How can I transform a barh matplot chart, for example, to a horizontal waterfall?
I want to create a HORIZONTAL waterfall.
For example, I am trying to make each bar in barh chart in matplotlib start at end of other, but I do not think I am approaching the problem the right way, because I have no results so far.
It should look like this:
Code to create the plot:
my_plot = trans.plot(
kind='barh',
stacked=True,
bottom=blank,legend=None,
figsize=(10, 5)
)
How do I separate the bars?
EDIT
I have found this ready to use python package, but it doesn't work with dataframes, so I cannot use it.
import waterfall_chart
from matplotlib import transforms
a = ['sales','returns','credit fees','rebates','late charges','shipping']
b = [10,-30,-7.5,-25,95,-7]
my_plot = waterfall_chart.plot(a, b, rotation_value=30, sorted_value=True, threshold=0.2,
formatting="$ {:,.1f}", net_label="end result", other_label="misc",
Title="chart", x_lab="X", y_lab="money", blue_color="blue",
green_color="#95ff24", red_color="r")
rot = transforms.Affine2D().rotate_deg(90)
my_plot.show()
I also found this tutorial, with code, for a vertical waterfall chart.
https://pbpython.com/waterfall-chart.html.
It works great, but I didn't manage to reproduce the same thing for a horizontal waterfall.

Related

How to plot line plot with vertical-based data (well-log)?

I was trying to plot geophysics data (well-log) into a scatter plot in Altair using mark_line function, but the line plot is not connecting the dots/ points from top-bottom, but rather from left-right. If you see figure on the left, the data is distributed vertically as clearly seen, in the middle is the result using mark_line, and on the right is the one I wanted, just flipped the X and Y axis.
Is there any way to make a plot to behave just like left figure, but in line encoding?
Or perhaps some form of hacks to flipped the display on the right figure?
chart1 = alt.Chart(w).mark_point(color='green').encode(
alt.X('GR', scale=alt.Scale(domain=[0,300])),
alt.Y('DEPT', scale=alt.Scale(domain=[7000, 7100])),
).interactive()
chart2 = alt.Chart(w).mark_line(color='green').encode(
alt.X('GR', scale=alt.Scale(domain=[0,300])),
alt.Y('DEPT', scale=alt.Scale(domain=[7000, 7100])),
).interactive()
chart3 = alt.Chart(w).mark_line(color='green').encode(
alt.Y('GR', scale=alt.Scale(domain=[0,300])),
alt.X('DEPT', scale=alt.Scale(domain=[7000, 7100])),
).interactive()
chart1 | chart2 | chart3
Plot using Altair
For those who needs more information, this is a typical dataset from borehole geophysics data/ well-log. Data (GR) is displayed in vertical line, against depth (DEPT).
Thanks for the help!
From what I tested so far, Altair scatters plot using mark_line will always follow the X-axis by default. Therefore, in the case where you want to plot data across Y-axis, one has to specify the order of the connecting line. In the following, I add order = 'DEPT' which was the Y-axis in the plot.
alt.Chart(
w
).mark_line(
color='green',
point=True,
).encode(
alt.X('GR', scale=alt.Scale(domain=[0,250])),
alt.Y('DEPT', sort = 'descending',scale=alt.Scale(domain=[7000, 7030])),
order = 'DEPT' #this has to be added to make sure the plot is following the order of Y-axis, DEPT
).configure_mark(
color = 'red'
).interactive()
Result:

How to place two charts next to each other in plotly python?

I am not using subplots for this since the requirement is of legend beside the chart which is not possible by using subplots. Subplots only lets the legend at once place, hence I have thought of using to different plots and placing them beside each other.
Here is the code which produced two charts, but i am unable to place them beside each other.
fig = go.Figure()
fig.add_trace(go.Scatter(x=data['time'],y=data['x'],mode='lines',name='xyz',hoverlabel=dict(bgcolor=['white']),hovertemplate='abcd<br>Probability: %{y}'))
fig.add_trace(go.Scatter(x=data['time'],y=predict_data['y'],mode='lines',name='abc'))
fig.update_layout(title='TRend charts',yaxis_title='Probabilities',autosize=False,width=1000,height=600,margin=dict(l=50,r=50,b=100,t=100,pad=4),paper_bgcolor='lightpink',xaxis_showgrid=False)
p_8 = opy.plot(fig,auto_open=False,output_type='div')
fig = go.Figure()
fig.add_trace(go.Scatter(x=data['time'],y=data['xy'],mode='lines',name='xyz1'))
fig.add_trace(go.Scatter(x=data['time'],y=data['ab'],mode='lines',name='abc`'))
fig.update_layout(title='Second Chart',yaxis_title='Probabilities',autosize=False,width=100,height=600,margin=dict(l=50,r=-50,b=100,t=100,pad=3),paper_bgcolor='yellow',xaxis_showgrid=False)
p_9 = opy.plot(fig,auto_open=False,output_type='div')
I get them one below the other. Any attributes which can get them beside each other?
Try this
fig = fig.make_subplots(rows=2, cols=1)

How to reproduce this legend with multiple curves?

I've been working hard on a package of functions for my work, and I'm stuck on a layout problem. Sometimes I need to work with a lot of columns subplots (1 row x N columns) and the standard matplotlib legend sometimes is not helpful and makes it hard to visualize all the data.
I've been trying to create something like the picture below. I already tried to create a subplot for the curves and another one for the legends (and display the x-axis scale as a horizontal plot). Also, I tried to spine the x-axis, but when I have a lot of curves plotted inside the same subplots the legend becomes huge.
The following image is from a software. I'd like to create a similar look. Notice that these legends are "static": it remains fixed independent of the zooming. Another observation is, I don't need all the ticks or anything like that.
What I'm already have is the following (the code is a mess, becouse I'm trying many different solutions and it is not organized nor pythonic yet.
import matplotlib.pyplot as plt
fig, ax = plt.subplots(1,2, sharey = True)
ax[0].semilogx(np.zeros_like(dados.Depth)+0.02, dados.Depth)
ax[0].semilogx(dados.AHT90, dados.Depth, label = 'aht90')
ax[0].set_xlim(0.2,2000)
ax[0].grid(True, which = 'both', axis = 'both')
axres1 = ax[0].twiny()
axres1.semilogx(dados.AHT90, dados.Depth, label = 'aht90')
axres1.set_xlim(0.2 , 2000)
axres1.set_xticks(np.logspace(np.log10(0.2),np.log10(2000),2))
axres1.spines["top"].set_position(("axes", 1.02))
axres1.get_xaxis().set_major_formatter(matplotlib.ticker.ScalarFormatter())
axres1.tick_params(axis='both', which='both', labelsize=6)
axres1.set_xlabel('sss')#, labelsize = 5)
axres2 = ax[0].twiny()
axres2.semilogx(dados.AHT10, dados.Depth, label = 'aht90')
axres2.set_xlim(0.2 , 2000)
axres2.set_xticks(np.logspace(np.log10(0.2),np.log10(2000),2))
axres2.spines["top"].set_position(("axes", 1.1))
axres2.get_xaxis().set_major_formatter(matplotlib.ticker.ScalarFormatter())
axres2.tick_params(axis='both', which='both', labelsize=6)
axres2.set_xlabel('aht10')#, labelsize = 5)
fig.show()
and the result is:
But well, I'm facing some issues on make a kind of make it automatic. If I add more curves, the prameter "set position" it is not practical to keep setting the position "by hand"
set_position(("axes", 1.02))
and another problem is, more curves I add, that kind of "legend" keep growing upward, and I have to adjust the subplot size with
fig.subplots_adjust(top=0.75)
And I'm also want to make the adjustment automatic, without keeping updating that parameter whenever I add more curves

How to plot 3D Bar chart/ Pie Chart/ Donut using Plotly

I have found code to make bar charts and pie charts in plotly also other 3D plots.
A simple bar chart works like this:
from plotly.offline import plot
from plotly.graph_objs import *
trace1 = Bar(
x=['cats', 'dogs', 'monkeys'],
y=[20, 14, 23]
)
data = Data([trace1])
plot(data)
Is there any option available in plotly to plot this bar graph in 3D layout. Also for pie chart/donut also?
Have a look at the official documentation:
https://plot.ly/python/3d-charts/
As this should be a list of all available 3D Charts in plot.ly:
No, it seems there is currently no option for 3D Bar/Pie/Donut.
See also: https://community.plot.ly/t/will-there-be-3d-bar-charts-in-the-future/1045/2
Bar/Pie/Donut are two-dimensional by nature, making them 3D would provide no additional value (apart from cosmetics)
As suggested in the link above, you could try using 3D filled line plots.
Though I doubt that the additional complexity required to get the desired result is worth it.
Still, 3D bar charts haven't been implemented in Plotly. There is a variant of 3D bar chart plotting function at https://github.com/buran21/barchart3d-plotly, intended for drawing of 1D labelled data. An example:
import plotly.data as pdata
from barchart3d import barchart3d
df = pdata.gapminder()
df = df[df['year'] == 2007].sort_values(by='pop', ascending=False).head(10)
fig = barchart3d(
df['country'].to_list(), (df['pop']/1e06).round(1).to_list(),
'Top 10 most populous countries in 2007 [Gapminder]', 'Population, mln',
colorscale='Bluered', opacity=0.6, flatshading=True)
fig.show()

plotting 2 graph in same window using matplotlib in python

I was plotting a line graph and a bar chart in matplotlib and both individually were working fine with my script.
but i'm facing a problem:
1. if i want to plot both graphs in the same output window
2. if i want to customize the display window to 1024*700
in 1 st case I was using subplot to plot two graphs in same window but i'm not being able to give both graphs their individual x-axis and y-axis names and also their individual title.
my failed code is:
import numpy as np
import matplotlib.mlab as mlab
import matplotlib.pyplot as plt
xs,ys = np.loadtxt("c:/users/name/desktop/new folder/x/counter.cnt",delimiter = ',').T
fig = plt.figure()
lineGraph = fig.add_subplot(211)
barChart = fig.add_subplot(212)
plt.title('DISTRIBUTION of NUMBER')
lineGraph = lineGraph.plot(xs,ys,'-') #generate line graph
barChart = barChart.bar(xs,ys,width=1.0,facecolor='g') #generate bar plot
plt.grid(True)
plt.axis([0,350,0,25]) #controlls axis for charts x first and then y axis.
plt.savefig('new.png',dpi=400)
plt.show()
but with this I am not being able to mark both graphs properly.
and also please site some idea about how to resize the window to 1024*700.
When you say
I was using subplot to plot two graphs in same window but i'm not being able to give both graphs their individual x-axis and y-axis names and also their individual title.
do you mean you want to set axis labels? If so try using lineGraph.set_xlabel and lineGraph.set_ylabel. Alternatively, call plt.xlabel and plot.ylabel just after you create a plot and before you create any other plots. For example
# Line graph subplot
lineGraph = lineGraph.plot(xs,ys,'-')
lineGraph.set_xlabel('x')
lineGraph.set_ylabel('y')
# Bar graph subplot
barChart = barChart.bar(xs,ys,width=1.0,facecolor='g')
barChart.set_xlabel('x')
barChart.set_ylabel('y')
The same applies to the title. Calling plt.title will add a title to the currently active plot. This is the last plot that you created or the last plot you actived with plt.gca. If you want a title on a specific subplot use the subplot handle: lineGraph.set_title or barChart.set_title.
fig.add_subplot returns a matplotlib Axes object. Methods on that object include set_xlabel and set_ylabel, as described by Chris. You can see the full set of methods available on Axes objects at http://matplotlib.sourceforge.net/api/axes_api.html.

Categories