11

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 am using pcolormesh and contourf. My problem is that pcolormesh is not having same size of the pitch: enter image description here

This is the code:

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

#print(x[1], y[1])
y = y[np.logical_not(np.isnan(y))]
x = x[np.logical_not(np.isnan(x))]
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()]))

fig = plt.figure(figsize=(9,10))
ax1 = fig.add_subplot(211)


ax1.pcolormesh(xi, yi, zi.reshape(xi.shape), alpha=0.5)

ax1.plot(y,x, "o")
ax1.set_xlim(0, 740)
ax1.set_ylim(515, 0)

#overlay soccer field
im = plt.imread('statszone_football_pitch.png')
ax1.imshow(im, extent=[0, 740, 0, 515], aspect='auto')


fig.savefig('pogba1516.png')

Here it is a link for the csv file: https://dl.dropboxusercontent.com/u/12348226/pogba_t1314.csv

slash89mf
  • 1,057
  • 2
  • 13
  • 35

1 Answers1

23

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:

enter image description here

Community
  • 1
  • 1
lanery
  • 5,222
  • 3
  • 29
  • 43
  • This way i get this error: ValueError: cannot convert float NaN to integer – slash89mf Apr 30 '16 at 17:58
  • That has got to be an issue with your `csv` data. Simple `nan` filtering can be done with `x = x[numpy.isfinite(x)]` and likewise with `y`. See this post for more: http://stackoverflow.com/questions/11620914/removing-nan-values-from-an-array – lanery Apr 30 '16 at 18:03
  • Is it possible to have zones like the heat map I posted before instead of rectangles (which are created by histogram2d) ? – slash89mf May 01 '16 at 15:55
  • A common method is to use a kernel-density estimate (KDE). Sorry for assuming, but I thought that since you imported gaussian_kde in your original code, that smoothing wasn't an issue. Give me a minute to update my answer. – lanery May 01 '16 at 16:48
  • Yes it was taken from an example found somewhere, but i can't get it working with histogram2d – slash89mf May 01 '16 at 17:00
  • Updated my answer. You may have luck looking elsewhere for info on how to overlay contours/pcolormesh on images. I did it sort of crudely by just setting the transparency with `alpha=0.5`. – lanery May 01 '16 at 17:18
  • it's very good! could you update your answer posting the whole code? I get errors like "name 'bins' is not defined" – slash89mf May 01 '16 at 17:24
  • Whoops, sorry about that. Should be fine now (replaced `bins` with `x.size**0.5` and `y.size**0.5`) – lanery May 01 '16 at 17:49
  • Please take a look to my new answer. Thank you – slash89mf May 01 '16 at 21:29
  • I updated my question, i have a strange result on the pcolormesh. Do you know why? @lanery – slash89mf May 03 '16 at 22:36
  • Your code looks ok to me, I can't tell from looking at it why your `pcolormesh` is misshaped. If you post your data (`pogba_t1314.csv`) somewhere and link to it, I can try to find where the issue is. – lanery May 04 '16 at 07:08
  • Just posted the link in the question (https://dl.dropboxusercontent.com/u/12348226/pogba_t1314.csv) – slash89mf May 04 '16 at 07:24
  • What about switching `xi` and `yi`? That is, `ax1.pcolormesh(yi, xi, zi.reshape(xi.shape), alpha=0.5)` – lanery May 04 '16 at 07:25
  • 1
    Oh, i missed it. Vary bad. Thank you! – slash89mf May 04 '16 at 07:28
  • How can I save the heatmap image? – Santhosh Dhaipule Chandrakanth Aug 16 '19 at 13:55