Python's Matplotlib plotting in wrong order

2020-01-24 03:01发布

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

enter image description here

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?

Thank you in advance!

6条回答
唯我独甜
2楼-- · 2020-01-24 03:36

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

enter image description here

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)

In both cases the output is

Output 2

enter image description here

查看更多
放荡不羁爱自由
3楼-- · 2020-01-24 03:44

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,

enter image description here

查看更多
你好瞎i
4楼-- · 2020-01-24 03:44

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

查看更多
爷的心禁止访问
5楼-- · 2020-01-24 03:44

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.

查看更多
一夜七次
6楼-- · 2020-01-24 03:47

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.

查看更多
ゆ 、 Hurt°
7楼-- · 2020-01-24 03:48

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

查看更多
登录 后发表回答