1

I have an arbitrary, large number (50-1000) of lists, representing X and Y coordinates, I'd like to plot them in one figure.

The lists are of different length, usually 100-1000 elements each. I get the lists as pairs of x and y coordinates (see example), but could easily convert them to 2xN arrays. They need to be plotted in order, from first to the last element. Each line separately.

Is there a way to pack all my lists to one (or two; x and y) object that matplotlib can read?

This example gives the wanted output but is unhandy when there is a lot of data.

I'm happy for a solution that takes advantage of numpy.

from matplotlib import pyplot as plt
fig, ax = plt.subplots(1,1)

x1 = [1,2,5] # usually much longer and a larger number of lists
y1 = [3,2,4]

x2 = [1,6,5,3]
y2 = [7,6,3,2]

x3 = [4]
y3 = [4]

for x, y, in zip([x1, x2, x3],[y1, y2, y3]):
    ax.plot(x,y, 'k.-')
plt.show()

Example

I would prefer something like this:

# f() is the function i need, to formats the data for plotting
X = f(x1, x2, x3) 
Y = f(y1, y2, y3)

#... so that I can do some processing of the arrays X, and Y here. 

ax.plot(X, Y, 'k.-')
user2821
  • 1,568
  • 2
  • 12
  • 16
  • how is you list data formatted? Post few lines. – Zaraki Kenpachi Jul 04 '19 at 10:39
  • I've updated the question. Lists are as in the example, but much longer and many more. – user2821 Jul 04 '19 at 10:46
  • 1
    i need to see you input data [few lines]. it is list of lists or something else. How this large number of list are stored? – Zaraki Kenpachi Jul 04 '19 at 10:49
  • I read the data from a specific binary file format. Each file contains one list of x values and one list of y values, however, I want to plot a large number of those pairs in one plot. E.g. all the files in a directory, usually above 50, up to 1000 or more. – user2821 Jul 04 '19 at 10:54
  • 1
    Do you want your plot to have as many segments as the number initial (pair of) list (here 3 including a point) ? Or is it ok for you to have all points connected together ? – jrjc Jul 04 '19 at 10:55
  • 1
    you can try this if you don't have any dots X = np.concatenate((x1,float('nan'),x2,float('nan'),x3),axis=None) Y = np.concatenate((y1,float('nan'),y2,float('nan'),y3),axis=None) – Aly Hosny Jul 04 '19 at 10:57
  • @jrjc Good question, I should clarify that I need them separate (otherwise I could just stack them together). – user2821 Jul 04 '19 at 11:00
  • 1
    From ~10 lines onwards it's [more efficient](https://stackoverflow.com/questions/54492963/many-plots-in-less-time-python/54544965#54544965) to use a `LineCollection`. – ImportanceOfBeingErnest Jul 04 '19 at 11:02
  • @ImportanceOfBeingErnest That makes good sense, thanks. I'll look into that! – user2821 Jul 04 '19 at 11:05

1 Answers1

1

You can use a LineCollection for that. Unfortunately, if you want to have markers in your lines, LineCollection does not support that, so you would need to do some trick like adding a scatter plot on top (see Adding line markers when using LineCollection).

from matplotlib import pyplot as plt
from matplotlib.collections import LineCollection

fig, ax = plt.subplots(1,1)

x1 = [1,2,5]
y1 = [3,2,4]

x2 = [1,6,5,3]
y2 = [7,6,3,2]

x3 = [4]
y3 = [4]

# Add lines
X = [x1, x2, x3]
Y = [y1, y2, y3]
lines = LineCollection((list(zip(x, y)) for x, y in zip(X, Y)),
                       colors='k', linestyles='-')
ax.add_collection(lines)
# Add markers
ax.scatter([x for xs in X for x in xs], [y for ys in Y for y in ys], c='k', marker='.')
# If you do not use the scatter plot you need to manually autoscale,
# as adding the line collection will not do it for you
ax.autoscale()

plt.show()

If you are working with arrays, you may also do as follows:

import numpy as np
# ...
X = [x1, x2, x3]
Y = [y1, y2, y3]
lines = LineCollection((np.stack([x, y], axis=1) for x, y in zip(X, Y)),
                       colors='k', linestyles='-')
ax.add_collection(lines)
ax.scatter(np.concatenate(X), np.concatenate(Y), c='k', marker='.')
ImportanceOfBeingErnest
  • 321,279
  • 53
  • 665
  • 712
jdehesa
  • 58,456
  • 7
  • 77
  • 121