Matplotlib plotting in wrong order
Question:
Basically I have two arrays, one containing the values of the x-axis and the second containing the values of the y-axis. The problem is, when I do
plt.semilogy(out_samp,error_mc)
I get this
Which doesn’t make any sense. That is because the plot functions plots everything as it encounters in the x array, not caring whether it’s sorted in ascending order or not. How can I sort these two arrays so that the x array is sorted by increasing value and the y axis sorted in the same way so that the points are the same but the plot is connected so that it doesn’t make this mess?
Answers:
You can convert your arrays to numpy arrays, then use argsort on the first array, take the the array and sort both arrays with the argsort array.
Sort by the value of x-axis before plotting. Here is an MWE.
import itertools
x = [3, 5, 6, 1, 2]
y = [6, 7, 8, 9, 10]
lists = sorted(itertools.izip(*[x, y]))
new_x, new_y = list(itertools.izip(*lists))
# import operator
# new_x = map(operator.itemgetter(0), lists) # [1, 2, 3, 5, 6]
# new_y = map(operator.itemgetter(1), lists) # [9, 10, 6, 7, 8]
# Plot
import matplotlib.pylab as plt
plt.plot(new_x, new_y)
plt.show()
For small data, zip
(as mentioned by other answerers) is enough.
new_x, new_y = zip(*sorted(zip(x, y)))
The result,
just do this
list=zip(*sorted(zip(*(x,y))))
plt.plot(*list)
sorted function will sort according to the 1st argument i.e x values
It is easier to zip
, sort and unzip
the two lists of data.
Example:
xs = [...]
ys = [...]
xs, ys = zip(*sorted(zip(xs, ys)))
plot(xs, ys)
See the zip documentation here: https://docs.python.org/3.5/library/functions.html#zip
I think you need to sort one array and the other array should also get sorted based on the first array. I got this solution from some other stack overflow question. Most probably this should be your solution.
out_samp,error_mc=zip(*sorted(zip(out_samp,error_mc)))
Now plot those two values, you get a correct graph.
An alternative to sort the lists would be to use NumPy arrays and use np.sort()
for sorting. The advantage with using arrays would be a vectorized operation while computing a function like y=f(x). Following is an example of plotting a normal distribution:
Without using sorted data
mu, sigma = 0, 0.1
x = np.random.normal(mu, sigma, 200)
f = 1/(sigma * np.sqrt(2 * np.pi)) *np.exp( - (x - mu)**2 / (2 * sigma**2) )
plt.plot(x,f, '-bo', ms = 2)
Output 1
With using np.sort() This allows straightforwardly using sorted array x
while computing the normal distribution.
mu, sigma = 0, 0.1
x = np.sort(np.random.normal(mu, sigma, 200))
# or use x = np.random.normal(mu, sigma, 200).sort()
f = 1/(sigma * np.sqrt(2 * np.pi)) *np.exp( - (x - mu)**2 / (2 * sigma**2) )
plt.plot(x,f, '-bo', ms = 2)
Alternatively if you already have both x and y data unsorted, you may use numpy.argsort
to sort them a posteriori
mu, sigma = 0, 0.1
x = np.random.normal(mu, sigma, 200)
f = 1/(sigma * np.sqrt(2 * np.pi)) *np.exp( - (x - mu)**2 / (2 * sigma**2) )
plt.plot(np.sort(x), f[np.argsort(x)], '-bo', ms = 2)
Notice that the code above uses sort()
twice: first with np.sort(x)
and then with f[np.argsort(x)]
. The total sort()
invocations can be reduced to one:
# once you have your x and f...
indices = np.argsort(x)
plt.plot(x[indices], f[indices], '-bo', ms = 2)
In both cases the output is
Output 2
Basically I have two arrays, one containing the values of the x-axis and the second containing the values of the y-axis. The problem is, when I do
plt.semilogy(out_samp,error_mc)
I get this
Which doesn’t make any sense. That is because the plot functions plots everything as it encounters in the x array, not caring whether it’s sorted in ascending order or not. How can I sort these two arrays so that the x array is sorted by increasing value and the y axis sorted in the same way so that the points are the same but the plot is connected so that it doesn’t make this mess?
You can convert your arrays to numpy arrays, then use argsort on the first array, take the the array and sort both arrays with the argsort array.
Sort by the value of x-axis before plotting. Here is an MWE.
import itertools
x = [3, 5, 6, 1, 2]
y = [6, 7, 8, 9, 10]
lists = sorted(itertools.izip(*[x, y]))
new_x, new_y = list(itertools.izip(*lists))
# import operator
# new_x = map(operator.itemgetter(0), lists) # [1, 2, 3, 5, 6]
# new_y = map(operator.itemgetter(1), lists) # [9, 10, 6, 7, 8]
# Plot
import matplotlib.pylab as plt
plt.plot(new_x, new_y)
plt.show()
For small data, zip
(as mentioned by other answerers) is enough.
new_x, new_y = zip(*sorted(zip(x, y)))
The result,
just do this
list=zip(*sorted(zip(*(x,y))))
plt.plot(*list)
sorted function will sort according to the 1st argument i.e x values
It is easier to zip
, sort and unzip
the two lists of data.
Example:
xs = [...]
ys = [...]
xs, ys = zip(*sorted(zip(xs, ys)))
plot(xs, ys)
See the zip documentation here: https://docs.python.org/3.5/library/functions.html#zip
I think you need to sort one array and the other array should also get sorted based on the first array. I got this solution from some other stack overflow question. Most probably this should be your solution.
out_samp,error_mc=zip(*sorted(zip(out_samp,error_mc)))
Now plot those two values, you get a correct graph.
An alternative to sort the lists would be to use NumPy arrays and use np.sort()
for sorting. The advantage with using arrays would be a vectorized operation while computing a function like y=f(x). Following is an example of plotting a normal distribution:
Without using sorted data
mu, sigma = 0, 0.1
x = np.random.normal(mu, sigma, 200)
f = 1/(sigma * np.sqrt(2 * np.pi)) *np.exp( - (x - mu)**2 / (2 * sigma**2) )
plt.plot(x,f, '-bo', ms = 2)
Output 1
With using np.sort() This allows straightforwardly using sorted array x
while computing the normal distribution.
mu, sigma = 0, 0.1
x = np.sort(np.random.normal(mu, sigma, 200))
# or use x = np.random.normal(mu, sigma, 200).sort()
f = 1/(sigma * np.sqrt(2 * np.pi)) *np.exp( - (x - mu)**2 / (2 * sigma**2) )
plt.plot(x,f, '-bo', ms = 2)
Alternatively if you already have both x and y data unsorted, you may use numpy.argsort
to sort them a posteriori
mu, sigma = 0, 0.1
x = np.random.normal(mu, sigma, 200)
f = 1/(sigma * np.sqrt(2 * np.pi)) *np.exp( - (x - mu)**2 / (2 * sigma**2) )
plt.plot(np.sort(x), f[np.argsort(x)], '-bo', ms = 2)
Notice that the code above uses sort()
twice: first with np.sort(x)
and then with f[np.argsort(x)]
. The total sort()
invocations can be reduced to one:
# once you have your x and f...
indices = np.argsort(x)
plt.plot(x[indices], f[indices], '-bo', ms = 2)
In both cases the output is
Output 2