176

I have a list of pairs (a, b) that I would like to plot with matplotlib in python as actual x-y coordinates. Currently, it is making two plots, where the index of the list gives the x-coordinate, and the first plot's y values are the as in the pairs and the second plot's y values are the bs in the pairs.

To clarify, my data looks like this: li = [(a,b), (c,d), ... , (t, u)] and I want to do a one-liner that just calls plt.plot(). If I didn't require a one-liner I could trivially do:

xs = [x[0] for x in li]
ys = [x[1] for x in li]
plt.plot(xs, ys)

How can I get matplotlib to plot these pairs as x-y coordinates?


Sample data

# sample data
li = list(zip(range(1, 14), range(14, 27)))

li → [(1, 14), (2, 15), (3, 16), (4, 17), (5, 18), (6, 19), (7, 20), (8, 21), (9, 22), (10, 23), (11, 24), (12, 25), (13, 26)]

Incorrect Plot

plt.plot(li)
plt.title('Incorrect Plot:\nEach index of the tuple plotted as separate lines')

enter image description here

Desired Plot

This produces the correct plot, but to many lines of code are used to unpack li. I need to unpack and plot with a single line of code, not multiple list-comprehensions.

xs = [x[0] for x in li]
ys = [x[1] for x in li]
plt.plot(xs, ys)
plt.title('Correct Plot:\nBut uses to many lines to unpack li')

enter image description here

cottontail
  • 10,268
  • 18
  • 50
  • 51
CodeKingPlusPlus
  • 15,383
  • 51
  • 135
  • 216
  • Essentially, this is a question about how to unpack a list of tuples, which is addressed with [Unpacking a list / tuple of pairs into two lists / tuples](https://stackoverflow.com/a/7558990/7758804). However, that answer doesn't show how to unpack the `zip` object into the plot API. – Trenton McKinney Jul 26 '22 at 20:54

3 Answers3

264

Given li in the question:

li = list(zip(range(1, 14), range(14, 27)))

To unpack the data from pairs into lists use zip:

x, y = zip(*li)

x → (1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13)
y → (14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26)

The one-liner uses the unpacking operator (*), to unpack the list of tuples for zip, and unpacks the zip object into the plot API.

plt.scatter(*zip(*li))

enter image description here

plt.plot(*zip(*li))

enter image description here

Trenton McKinney
  • 56,955
  • 33
  • 144
  • 158
sashkello
  • 17,306
  • 24
  • 81
  • 109
67

If you have a numpy array you can do this:

import numpy as np
from matplotlib import pyplot as plt

data = np.array([
    [1, 2],
    [2, 3],
    [3, 6],
])
x, y = data.T
plt.scatter(x,y)
plt.show()
cs01
  • 5,287
  • 1
  • 29
  • 28
Zweedeend
  • 2,565
  • 2
  • 17
  • 21
  • 3
    So there is no way to have a `np.array` of `data=np.array([[x1,y1],[x2,y2],etc.])` and using `plt.plot(data)`. I'll always have to give two arrays instead of arrays of arrays? – Max Coplan Dec 03 '18 at 16:15
  • 2
    @MaxCoplan, that's right, but you could use `plt.plot(*data.T)` which does the same as the above but skips the intermediate step. – Zweedeend Nov 14 '19 at 07:37
13

If you want to plot a single line connecting all the points in the list

plt.plot(li[:])

plt.show()

This will plot a line connecting all the pairs in the list as points on a Cartesian plane from the starting of the list to the end. I hope that this is what you wanted.

David Beauchemin
  • 231
  • 1
  • 2
  • 12
Shubham Rana
  • 217
  • 2
  • 3
  • 5
    He didn't want to plot a single line, he wanted to plot with a "one-liner" (a single line of code). The answer he was looking for (and got 3 years ago) was to use `scatter()`. – Dartmouth Feb 26 '17 at 18:07
  • 2
    @Gathide: Yes, it deserves a downvote, since it doesn't work at all, and doesn't fit the description. `plt.plot(li)` is just like `plt.plot(li[:])`. It simply plots 2 lines, using the pairs as `(y1, y2)` and not as `(x1, y1)`. – Eric Duminil Apr 12 '21 at 18:36
  • 1
    The comment by @Dartmouth is only half correct. The OP wants to generate one plot line, with a one-liner. The OP states _**If I didn't require a one-liner I could trivially do**_, followed by the code to produce a single line. This answer does not solve the question. It produces the same unwanted double line plot the OP already has. – Trenton McKinney Jul 26 '22 at 21:14