slash89mf - 1 year ago 874

Python Question

I have a list of coordinates:

`y,x`

445.92,483.156

78.273,321.512

417.311,204.304

62.047,235.216

87.24,532.1

150.863,378.184

79.981,474.14

258.894,87.74

56.496,222.336

85.105,454.176

80.408,411.672

90.656,433.568

378.027,441.296

433.964,290.6

453.606,317.648

383.578,115.432

128.232,312.496

116.276,93.536

94.072,222.336

52.226,327.308

321.663,187.56

392.972,279.008

I would like to plot a density map (or heat map) based on these points, using matplotlib. I saw that

`pcolor`

`pcolormesh`

I want to plot them on top of a png image (soccer pitch) to have something like this:

This is my code:

`import matplotlib.pyplot as plt`

import matplotlib

import numpy as np

from scipy.stats import gaussian_kde

im = plt.imread('statszone_football_pitch.png')

implot = plt.imshow(im, aspect='auto')

xlim, ylim = plt.xlim(), plt.ylim()

dpi=90

fig = plt.figure(figsize=(620/dpi, 579/dpi), dpi=dpi)

ax = fig.add_axes([0, 0, 1, 1], frame_on=False)

ax.xaxis.set_visible(False)

ax.yaxis.set_visible(False)

ax.imshow(im, interpolation='none')

y, x = np.genfromtxt('coordinate_tackle_success.csv', delimiter=',', unpack=True)

#plt.plot(x,y, "o")

plt.xlim(xlim)

plt.ylim(ylim)

Z = np.exp(-((x-1)**2+y**2))

# Plot the density map using nearest-neighbor interpolation

plt.pcolormesh(x,y,Z)

plt.savefig('tackles.png')

This give me an error:

`Traceback (most recent call last):`

File "tackles.py", line 27, in <module>

plt.pcolormesh(x,y,Z)

File "/usr/local/lib/python2.7/site-packages/matplotlib/pyplot.py", line 3093, in pcolormesh

ret = ax.pcolormesh(*args, **kwargs)

File "/usr/local/lib/python2.7/site-packages/matplotlib/__init__.py", line 1812, in inner

return func(ax, *args, **kwargs)

File "/usr/local/lib/python2.7/site-packages/matplotlib/axes/_axes.py", line 5395, in pcolormesh

X, Y, C = self._pcolorargs('pcolormesh', *args, allmatch=allmatch)

File "/usr/local/lib/python2.7/site-packages/matplotlib/axes/_axes.py", line 4995, in _pcolorargs

numRows, numCols = C.shape

ValueError: need more than 1 value to unpack

Answer Source

This will hopefully get you started on the right track, but I would definitely recommend reading the docs for `pcolor`

and `pcolormesh`

.

You have commented `# Plot the density map using nearest-neighbor interpolation`

, but since `Z`

is a 1D array, you don't have any 2D density data for a density map. Density maps are most easily created through the use of `np.histogram2d`

as I'll show below using your data.

```
Z, xedges, yedges = np.histogram2d(x, y)
```

`Z`

is now a 2D array that has information about the distribution of your x, y coordinates. This distribution can be plotted with `pcolormesh`

like so

```
plt.pcolormesh(xedges, yedges, Z.T)
```

Sort of a ways to go before you obtain an image like the one you posted, but it should explain your error and help get you on the right track.

**Update: For nicer, smoother density maps**

Assuming you have two 1D arrays, `x`

and `y`

you can use a kernel density estimate to obtain much nicer heatmaps in the following way [reference],

```
from scipy.stats.kde import gaussian_kde
k = gaussian_kde(np.vstack([x, y]))
xi, yi = np.mgrid[x.min():x.max():x.size**0.5*1j,y.min():y.max():y.size**0.5*1j]
zi = k(np.vstack([xi.flatten(), yi.flatten()]))
```

Now you can plot the Gaussian KDE with either `pcolormesh`

or `contourf`

depending on what kind of effect/aesthetics you're after

```
import matplotlib.pyplot as plt
fig = plt.figure(figsize=(7,8))
ax1 = fig.add_subplot(211)
ax2 = fig.add_subplot(212)
# alpha=0.5 will make the plots semitransparent
ax1.pcolormesh(xi, yi, zi.reshape(xi.shape), alpha=0.5)
ax2.contourf(xi, yi, zi.reshape(xi.shape), alpha=0.5)
ax1.set_xlim(x.min(), x.max())
ax1.set_ylim(y.min(), y.max())
ax2.set_xlim(x.min(), x.max())
ax2.set_ylim(y.min(), y.max())
# you can also overlay your soccer field
im = plt.imread('soccerPitch.jpg')
ax1.imshow(im, extent=[x.min(), x.max(), y.min(), y.max()], aspect='auto')
ax2.imshow(im, extent=[x.min(), x.max(), y.min(), y.max()], aspect='auto')
```

I get this image: