Boundary histograms / graph lines as in FACS
My question is mostly different from this , but for matplotlib. I'm sure it has something to do with axes or subplots, but I don't think I fully understand these paradigms (a fuller explanation would be great).
When I go through a set of comparisons, I would like the base value of each new graph to be slightly lower than the previous one, in order to get something like this:
Another (potential) wrinkle is that I generate these plots in a loop, so I don't necessarily know how many areas there will be at the very beginning. I think this is one of those things I get on a day to day basis with subplots / axes because it seems like you need to set them up ahead of time.
Any ideas will be very grateful.
EDIT: I've made little progress, I think:
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
x = np.random.random(100)
y = np.random.random(100)
fig = plt.figure()
ax = fig.add_axes([1,1,1,1])
ax2 = fig.add_axes([1.02,.9,1,1])
ax.plot(x, color='red')
ax.fill_between([i for i in range(len(x))], 0, x, color='red', alpha=0.5)
ax2.plot(y, color='green')
ax2.fill_between([i for i in range(len(y))], 0, y, color='green', alpha=0.5)
Which is close to what I want ...
source to share
Is this what you want?
What I did was define the y distance between the baselines of each curve. For the i-th curve, I calculated the minimum Y value, then set the minimum to be i times the y-distance, adjusting the height of the entire curve accordingly. I used a decreasing z-order to ensure that the filled portion of the curves was not shaded by the baselines.
Here's the code:
import numpy as np
import matplotlib.pyplot as plt
delta_Y = .5
zorder = 0
for i, Y in enumerate(data):
baseline = min(Y)
#change needed for minimum of Y to be delta_Y above previous curve
y_change = delta_Y * i - baseline
Y = Y + y_change
plt.fill_between(np.linspace(0, 1000, 1000), Y, np.ones(1000) * delta_Y * i, zorder = zorder)
zorder -= 1
Code that generates dummy data:
def gauss(X):
return np.exp(-X**2 / 2.0)
#create data
X = np.linspace(-10, 10, 100)
data = []
for i in xrange(10):
arr = np.zeros(1000)
arr[i * 100: i * 100 + 100] = gauss(X)
data.append(arr)
data.reverse()
source to share
You can also explore JoyPy installation via:
pip install joypy
A fairly dynamic tool created by Leonardo Taccari, if you look at "stacked" distribution plots like this:
Example 1 - Plot of joy using JoyPy:
Example 2 - Plot of joy in aperture dataset:
Leonardo also has a neat description of the package and how to use it here .
Alternatively Seaborn has a package , but I found it less easy to use.
Hope it helps!
source to share
This way I was able to get a little further by adding an extra Axes instance to each loop.
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
#instantiate data sets
x = np.random.random(100)
y = np.random.random(100)
z = np.random.random(100)
plots = [x, y, z]
fig = plt.figure()
#Sets the default vertical position
pos = 1
def making_plot(ax, p):
ax.plot(p)
# Prevents the background from covering over the earlier plots
ax.set_axis_bgcolor('none')
for p in plots:
ax = fig.add_axes([1,pos,1,1])
pos -= 0.3
making_plot(ax, p)
plt.show()
Clearly I could have spent more time making this prettier, but it does the job.
source to share