Merge two existing plots into one plot - python

I haven't really attempted any way to do this, but I am wondering if there is a way to merge two plots that already exist into one graph. Any input would be greatly appreciated!

Here is a complete minimal working example that goes through all the steps you need to extract and combine the data from multiple plots.
import numpy as np
import pylab as plt
# Create some test data
secret_data_X1 = np.linspace(0,1,100)
secret_data_Y1 = secret_data_X1**2
secret_data_X2 = np.linspace(1,2,100)
secret_data_Y2 = secret_data_X2**2
# Show the secret data
plt.subplot(2,1,1)
plt.plot(secret_data_X1,secret_data_Y1,'r')
plt.plot(secret_data_X2,secret_data_Y2,'b')
# Loop through the plots created and find the x,y values
X,Y = [], []
for lines in plt.gca().get_lines():
for x,y in lines.get_xydata():
X.append(x)
Y.append(y)
# If you are doing a line plot, we don't know if the x values are
# sequential, we sort based off the x-values
idx = np.argsort(X)
X = np.array(X)[idx]
Y = np.array(Y)[idx]
plt.subplot(2,1,2)
plt.plot(X,Y,'g')
plt.show()

Assuming you are using Matplotlib, you can get the data for a figure as an NX2 numpy array like so:
gca().get_lines()[n].get_xydata()

Related

Set output range of matplotlib - imshow

For a project I'm working on I have created two sets of data which is made from a function that takes two input and returns a 3rd. I am currently using a matplotlib imshow graph to show the data. As one of the data sets contains far higher values than the other data set so I was hoping to set a range for both meaning the colours would represent the same value across the two charts. Is there a good way to do this? thankyou
Here is the code I am currently using:
import matplotlib.pyplot as plt
import json
import numpy as np
with open("multi_testing\out_put\\bit_shift.txt","r") as f:
n = json.loads(f.read())
n = n[0]
inp = np.array(n)
fig, ax = plt.subplots()
im = ax.imshow(inp)
ax.invert_yaxis()
ax.set_title("bit shifting")
fig.tight_layout()
plt.show()
and here are the two data sets:
[[[7,7,7,7,7,7,7,7,7,7,7],[11,11,11,11,11,11,11,11,11,11,11],[15,15,15,15,15,15,15,15,15,15,15],[19,19,19,19,19,19,19,19,19,19,19],[23,23,23,23,23,23,23,23,23,23,23],[27,27,27,27,27,27,27,27,27,27,27],[31,31,31,31,31,31,31,31,31,31,31],[35,35,35,35,35,35,35,35,35,35,35],[39,39,39,39,39,39,39,39,39,39,39],[43,43,43,43,43,43,43,43,43,43,43],[47,47,47,47,47,47,47,47,47,47,47]]]
and
[[[10,19,26,28,33,35,35,37,40,42,42],[10,19,26,28,33,35,35,37,40,42,42],[10,19,26,28,33,35,35,37,40,42,42],[10,19,26,28,33,35,35,37,40,42,42],[10,19,26,28,33,35,35,37,40,42,42],[10,19,26,28,33,35,35,37,40,42,42],[10,19,26,28,33,35,35,37,40,42,42],[10,19,26,28,33,35,35,37,40,42,42],[10,19,26,28,33,35,35,37,40,42,42],[10,19,26,28,33,35,35,37,40,42,42],[10,19,26,28,33,35,35,37,40,42,42]]]
You can use vmin and vmax for this while using ax.imshow(). For example:
im = ax.imshow(inp, vmin=0, vmax=50)

Python Plot of Array Produces Two Lines Instead of One

Plotted an array generated from comma separated files and it plotted two lines instead of the correct one (orange). If any one has could offer a solution or any suggestions it would be greatly appreciated!
import numpy as np
import matplotlib.pyplot as plt
file = open("com.txt","r")
X, Y = [], []
npy_array = np.loadtxt(file, delimiter=",")
plt.plot(npy_array)
plt.show()
enter image description here
It seems that you have loaded tabulated data into a 2d array. You need to separate this into independent and dependent variables and then plot one against the other, rather than plot both lines against the array index. (Clearly the linearly increasing data in your blue line is intended to be the independent variable, and should be your "x" values, ranging from 0 to approximately 0.2.) Assuming that the lines of the file are in the order x,y, you would do this -- otherwise swap the 0 and 1.
# to start with, some lines unchanged from the question
import numpy as np
import matplotlib.pyplot as plt
file = open("com.txt","r")
npy_array = np.loadtxt(file, delimiter=",")
# below here: what you need to change
x = npy_array[:,0]
y = npy_array[:,1]
plt.plot(x, y)
matplotlib plots 2d numpy arrays assuming each column is a different set of data, and should each be plotted indigently
a = [[0,1,2,3], [0,2,3,6]]
np_a = np.array(a)
plt.plot(np_a,'x:')
plt.show()
because the line is a strait one, I assume you want that to be your x axis. To do that you have to pass the x axis as the first perimeter, and the y axis as the second
a = [[0,1,2,3], [0,2,3,6]]
np_a = np.array(a)
plt.plot(np_a[0],np_a[1],'x:')
plt.show()

Grid of plots with lines overplotted in matplotlib

I have a dataframe that consists of a bunch of x,y data that I'd like to see in scatter form along with a line. The dataframe consists of data with its form repeated over multiple categories. The end result I'd like to see is some kind of grid of the plots, but I'm not totally sure how matplotlib handles multiple subplots of overplotted data.
Here's an example of the kind of data I'm working with:
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
category = np.arange(1,10)
total_data = pd.DataFrame()
for i in category:
x = np.arange(0,100)
y = 2*x + 10
data = np.random.normal(0,1,100) * y
dataframe = pd.DataFrame({'x':x, 'y':y, 'data':data, 'category':i})
total_data = total_data.append(dataframe)
We have x data, we have y data which is a linear model of some kind of generated dataset (the data variable).
I had been able to generate individual plots based on subsetting the master dataset, but I'd like to see them all side-by-side in a 3x3 grid in this case. However, calling the plots within the loop just overplots them all onto one single image.
Is there a good way to take the following code block and make a grid out of the category subsets? Am I overcomplicating it by doing the subset within the plot call?
plt.scatter(total_data['x'][total_data['category']==1], total_data['data'][total_data['category']==1])
plt.plot(total_data['x'][total_data['category']==1], total_data['y'][total_data['category']==1], linewidth=4, color='black')
If there's a simpler way to generate the by-category scatter plus line, I'm all for it. I don't know if seaborn has a similar or more intuitive method to use than pyplot.
You can use either sns.FacetGrid or manual plt.plot. For example:
g = sns.FacetGrid(data=total_data, col='category', col_wrap=3)
g = g.map(plt.scatter, 'x','data')
g = g.map(plt.plot,'x','y', color='k');
Gives:
Or manual plt with groupby:
fig, axes = plt.subplots(3,3)
for (cat, data), ax in zip(total_data.groupby('category'), axes.ravel()):
ax.scatter(data['x'], data['data'])
ax.plot(data['x'], data['y'], color='k')
gives:

How to extract x,y data from kdensity plot from matplotlib for python

I am trying to figure out how to make a 3d figure of uni-variate kdensity plots as they change over time (since they pull from a sliding time window of data over time).
Since I can't figure out how to do that directly, I am first trying to get the x,y plotting data for kdensity plots of matplotlib in python. I hope after I extract them I can use them along with a time variable to make a three dimensional plot.
I see several posts telling how to do this in Matlab. All reference getting Xdata and Ydata from the underlying figure:
x=get(h,'Xdata')
y=get(h,'Ydata')
How about in python?
The answer was already contained in another thread (How to create a density plot in matplotlib?). It is pretty easy to get a set of kdensity x's and y's from a set of data.
import matplotlib.pyplot as plt
import numpy as np
from scipy.stats import gaussian_kde
data = [1.5]*7 + [2.5]*2 + [3.5]*8 + [4.5]*3 + [5.5]*1 + [6.5]*8 # data is a set of univariate data
xs = np.linspace(0,max(data),200) # This 200 sets the # of x (and so also y) points of the kdensity plot
density = gaussian_kde(data)
density.covariance_factor = lambda : .25
density._compute_covariance()
ys = density(xs)
plt.plot(xs,ys)
And there you have it. Both the kdensity plot and it's underlying x,y data.
Not sure how kdensity plots work, but note that matplotlib.pyplot.plot returns a list of the added Line2D objects, which are, in fact, where the X and Y data are stored. I suspect they did that to make it work similarly to MATLAB.
import matplotlib.pyplot as plt
h = plt.plot([1,2,3],[2,4,6]) # [<matplotlib.lines.Line2D object at 0x021DA9F0>]
x = h[0].get_xdata() # [1,2,3]
y = h[0].get_ydata() # [2,4,6]

Python Matplotlib: plotting histogram with overlapping boundaries removed

I am plotting a histogram using Matplotlib in Python with the matplotlib.bar() function. This gives me plots that look like this:
I am trying to produce a histogram that only plots the caps of each bar and the sides that don't directly share space with the border of another bar, more like this: (I edited this using gimp)
How can I achieve this using Python? Answers using matplotlib are preferable since that is what I have the most experience with but I am open to anything that works using Python.
For what it's worth, here's the relevant code:
import numpy as np
import matplotlib.pyplot as pp
bin_edges, bin_values = np.loadtxt("datafile.dat",unpack=True)
bin_edges = np.append(bin_edges,500.0)
bin_widths = []
for j in range(len(bin_values)):
bin_widths.append(bin_edges[j+1] - bin_edges[j])
pp.bar(bin_edges[:-1],bin_values,width=bin_widths,color="none",edgecolor='black',lw=2)
pp.savefig("name.pdf")
I guess the easiest way is to use the step function instead of bar:
http://matplotlib.org/examples/pylab_examples/step_demo.html
Example:
import numpy as np
import matplotlib.pyplot as pp
# Simulate data
bin_edges = np.arange(100)
bin_values = np.exp(-np.arange(100)/5.0)
# Prepare figure output
pp.figure(figsize=(7,7),edgecolor='k',facecolor='w')
pp.step(bin_edges,bin_values, where='post',color='k',lw=2)
pp.tight_layout(pad=0.25)
pp.show()
If your bin_edges given represent the left edge use where='post'; if they are the rightern side use where='pre'. The only issue I see is that step doesn't really plot the last (first) bin correctly if you use post (pre). But you could just add another 0 bin before/after your data to make it draw everything properly.
Example 2 - If you want to bin some data and draw a histogram you could do something like this:
# Simulate data
data = np.random.rand(1000)
# Prepare histogram
nBins = 100
rng = [0,1]
n,bins = np.histogram(data,nBins,rng)
x = bins[:-1] + 0.5*np.diff(bins)
# Prepare figure output
pp.figure(figsize=(7,7),edgecolor='k',facecolor='w')
pp.step(x,n,where='mid',color='k',lw=2)
pp.show()

Categories