How to plot a bar plot in realtime using matplotlib - python

I've a continuous stream of data which is basically bins of a histogram.
I can plot a in real-time if use something like following:
import pylab as plt
from matplotlib.pyplot import figure, show
import numpy as np
plt.ion()
X = np.linspace(0,4095,16)
Y = np.linspace(0,10000,16)
f, axarr = plt.subplots(4, sharex=True)
graph_low, = axarr[0].plot(X,Y,label='SomeLabel')
graph_low.set_ydata(Z)
But this only plots a line-plot.
The issue is I can't find something similar to set_ydata for a bar plot.

Does this do the job for you?
ax = plt.bar(left, height)
ax.patches[i].set_height(x)
where i is the index for a particular bar and x is the desired height.

Related

Plot lineplot on top of seaborn heatmap using same axes

I have seaborn heatmap and I would like to plot a lineplot on top of it while using the same x and y axis that the heatmap is using.
I expected the line to behave like in this post and take up most of the space of the heatmap, but instead the output I got was the following plot where it only occupied a small section of the heatmap. How can I make the line take up most of the space in the heatmap?
Below is the minimal working example that produced the plot I linked above.
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
import pandas as pd
num = 11
a = np.eye(num)
x = np.round(np.linspace(0, 1, num=num), 1)
y = np.round(np.linspace(0, 1, num=num), 1)
df = pd.DataFrame(a, columns=x, index=y)
f, ax = plt.subplots()
ax = sns.heatmap(df, cbar=False)
ax.axes.invert_yaxis()
sns.lineplot(x=x, y=y)
plt.show()
Perhaps just a simple fix here:
sns.lineplot(x=x*num, y=y*num)

How do I format matplotlib stacked area chart axis to show only range given?

I'm trying to create a simple stacked area chart. Here is my code:
x = [1990,1995,2000,2005,2010]
y = [df['a'],df['b'],df['c']]
...
plt.stackplot(x,y, labels=['a,b,c'], ...)
...
plt.show()
However, x-axis on the graph created goes up in intervals of 2.5 so it looks like this:
1990.0, 1992.5, 1995.0....
How do I change it so that the graph created on the x-axis goes up in intervals of 5?
You can create a subplot and set the major and minor locators of x axis like this:
import matplotlib.pyplot as plt
from matplotlib.ticker import (AutoMinorLocator, MultipleLocator)
fig, ax = plt.subplots()
ax.set_xlim(1990, 2015)
ax.xaxis.set_major_locator(MultipleLocator(5))
ax.xaxis.set_minor_locator(AutoMinorLocator(1))
plt.stackplot(x,y, labels=['a,b,c'], ...)
plt.show()

How to create legend with proxy artist for contourf plot in Matplotlib

I am trying to create a graphic where I overlay multiple contour plots on a single image. So I want to have colorbars for each of the plots, as well as a legend indicating what each contour represents. However Matplotlib will not allow me to create a separate legend for my contour plots. Simple example:
import matplotlib as mpl
import matplotlib.pyplot as plt
import cartopy
import cartopy.crs as ccrs
import numpy as np
def create_contour(i,j):
colors = ["red","green","blue"]
hatches = ['-','+','x','//','*']
fig = plt.figure()
ax = plt.axes(projection=ccrs.PlateCarree())
ax.set_extent((-15.0,15.0,-15.0,15.0))
delta = 0.25
x = np.arange(-3.0,3.0,delta)
y = np.arange(-2.0,2.0,delta)
X, Y = np.meshgrid(x, y)
data = np.full(np.shape(X), 1.0)
plot = ax.contourf(X,Y,data, levels = [float(i),float(i+1)], hatch=[hatches[j]], colors = colors[i], label="label")
plt.legend(handles=[plot], labels=["label"])
plt.savefig("figure_"+str(i)+".png")
create_contour(1,3)
When I run this, I get the following message:
UserWarning: Legend does not support
(matplotlib.contour.QuadContourSet object at 0x7fa69df7cac8)
instances. A proxy artist may be used instead. See:
http://matplotlib.org/users/legend_guide.html#creating-artists-specifically-for-adding-to-the-legend-aka-proxy-artists
"aka-proxy-artists".format(orig_handle)
But as far as I can tell, I am following those directions as closely as possible, the only difference being that they do not use contourf in the example.
Any help would be greatly appreciated.
The comments to your question look like they have solved the question (by making custom patches and passing those through to the legend). There is also an example that I added many years ago to the matplotlib documentation to do something similar (about the same time I added contour hatching to matplotlib): https://matplotlib.org/examples/pylab_examples/contourf_hatching.html#pylab-examples-contourf-hatching
It is such a reasonable request that there is even a method on the contour set to give you legend proxies out of the box: ContourSet.legend_elements.
So your example might look something like:
%matplotlib inline
import matplotlib.pyplot as plt
import cartopy.crs as ccrs
import numpy as np
fig = plt.figure(figsize=(10, 10))
ax = plt.axes(projection=ccrs.PlateCarree())
ax.coastlines('10m')
y = np.linspace(40.0, 60.0, 30)
x = np.linspace(-10.0, 10.0, 40)
X, Y = np.meshgrid(x, y)
data = 2*np.cos(2*X**2/Y) - np.sin(Y**X)
cs = ax.contourf(X, Y, data, 3,
hatches=['//','+','x','o'],
alpha=0.5)
artists, labels = cs.legend_elements()
plt.legend(handles=artists, labels=labels)
plt.show()

Get actual numbers instead of normalized value in seaborn KDE plots

I have three dataframes and I plot the KDE using seaborn module in python. The issue is that these plots try to make the area under the curve 1 (which is how they are intended to perform), so the height in the plots are normalized ones. But is there any way to show the actual values instead of the normalized ones. Also is there any way I can find out the point of intersection for the curves?
Note: I do not want to use the curve_fit method of scipy as I am not sure about the distribution I will get for each dataframe, it can be multimodal also.
import seaborn as sns
plt.figure()
sns.distplot(data_1['gap'],kde=True,hist=False,label='1')
sns.distplot(data_2['gap'],kde=True,hist=False,label='2')
sns.distplot(data_3['gap'],kde=True,hist=False,label='3')
plt.legend(loc='best')
plt.show()
Output for the code is attached in the link as I can't post images.plot_link
You can just grab the line and rescale its y-values with set_data:
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
# create some data
n = 1000
x = np.random.rand(n)
# plot stuff
fig, ax = plt.subplots(1,1)
ax = sns.distplot(x, kde=True, hist=False, ax=ax)
# find the line and rescale y-values
children = ax.get_children()
for child in children:
if isinstance(child, matplotlib.lines.Line2D):
x, y = child.get_data()
y *= n
child.set_data(x,y)
# update y-limits (not done automatically)
ax.set_ylim(y.min(), y.max())
fig.canvas.draw()

Programmatically drawing overlaid offset plots in matplotlib

I have 3 different plots that are currently each saved as separate figures. However, due to space constraints I would like to layer them behind each other and offset like so:
I am trying to convey that a similar pattern exists across each plot and this is a nice and compact way of doing so. I would like to programmatically draw such a figure using matplotlib, but I'm not sure how to layer and offset the graphs using the usual pyplot commands. Any suggestions would be helpful. The following code is a skeleton of what I have currently.
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
window = 100
xs = np.arange(100)
ys = np.zeros(100)
ys[80:90] = 1
y2s = np.random.randn(100)/5.0+0.5
with sns.axes_style("ticks"):
for scenario in ["one", "two", "three"]:
fig = plt.figure()
plt.plot(xs, ys)
plt.plot(xs, y2s)
plt.title(scenario)
sns.despine(offset=10)
You can manually create the axes to plot into and position them as you like.
To highlight this approach modified your example as follows
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
window = 100
xs = np.arange(100)
ys = np.zeros(100)
ys[80:90] = 1
y2s = np.random.randn(100)/5.0+0.5
fig = plt.figure()
with sns.axes_style("ticks"):
for idx,scenario in enumerate(["one", "two", "three"]):
off = idx/10.+0.1
ax=fig.add_axes([off,off,0.65,0.65], axisbg='None')
ax.plot(xs, ys)
ax.plot(xs, y2s)
ax.set_title(scenario)
sns.despine(offset=10)
which gives a plot like
Here, I used fig.add_axes to add manually created axes objects to the predefined figure object. The arguments specify the position and size of the newly created axes, see docs.
Note that I also set the axes background to be transparent (axisbg='None').

Categories

Resources