Make a heatmap of x,y,z data in Python - python

I am trying to draw a heatmap in Python.
I have studied several tutorials but still can't achieve what I need.
My data has 3 columns: X, Y (coordinates in the scatterplot) and cluster (a group/cluster each row is placed). The desired output should look like that (6 clusters and X,Y points distributed in the coloured areas):
My current code:
# libraries
import pandas as pd
import matplotlib.pyplot as plt
import numpy as np
from scipy.stats import kde
from scipy.interpolate import griddata
# Get the data (csv file is hosted on the web)
url = 'https://raw.githubusercontent.com/ampil/sandbox/master/latest-sales-sample.csv'
df = pd.read_csv(url, sep = ';')
df = df.dropna(axis=0, how='any', thresh=None, subset=None, inplace=False)
# create data
x = df['X']
y = np.log(df['Y'])
z = df['cluster']
# target grid to interpolate to
xi = yi = np.arange(0, 1.01, 0.01)
xi, yi = np.meshgrid(xi,yi)
# interpolate
zi = griddata((x,y),z,(xi,yi),method='cubic')
# plot
fig = plt.figure()
ax = fig.add_subplot(111)
ax.axis((x.min(), x.max(), y.min(), y.max()))
plt.contourf(xi, yi, zi, np.arange(0, 1.01, 0.01), cmap='coolwarm')
plt.plot(x,y,'k.')
plt.xlabel('x',fontsize=16)
plt.ylabel('y',fontsize=16)
plt.show()
plt.close(fig)
gives me
Later on, I plan to publish the graph via dash.
Any help is appreciated!

My answer is a small edit to answer provided by warped.
The difference is the inclusion of the parameter 'extend' in the contourf method call.
https://matplotlib.org/3.1.1/api/_as_gen/matplotlib.pyplot.contourf.html
For some more information about the minimum/maximum color-map behaviour, see:
https://matplotlib.org/3.1.1/gallery/images_contours_and_fields/contourf_demo.html#sphx-glr-gallery-images-contours-and-fields-contourf-demo-py
# libraries
import pandas as pd
import matplotlib.pyplot as plt
import numpy as np
from scipy.stats import kde
from scipy.interpolate import griddata
# Get the data (csv file is hosted on the web)
url = 'https://raw.githubusercontent.com/ampil/sandbox/master/latest-sales-sample.csv'
df = pd.read_csv(url, sep = ';')
df = df.dropna(axis=0, how='any', thresh=None, subset=None, inplace=False)
# create data
x = df['X']
y = np.log(df['Y'])
z = df['cluster']
#following 2 lines provided by user-warped
xi = np.arange(0, np.max(x), 0.1)
yi = np.arange(0, np.max(y), 0.1)
xi, yi = np.meshgrid(xi,yi)
# interpolate
zi = griddata((x,y),z,(xi,yi),method='cubic')
#define color map...which you can choose to modify with 'set_under' and 'set_over'
#as per: https://matplotlib.org/3.1.1/gallery/images_contours_and_fields/contourf_demo.html#sphx-glr-gallery-images-contours-and-fields-contourf-demo-py
cmap = plt.cm.get_cmap("coolwarm")
fig = plt.figure()
ax = fig.add_subplot(111)
ax.axis((x.min(), x.max(), y.min(), y.max()))
#added the 'extend' parameter to user:warped edit as per documentation of plt.contourf
#https://matplotlib.org/3.1.1/api/_as_gen/matplotlib.pyplot.contourf.html
plt.contourf(xi, yi, zi, levels=[1,2,3,4,5,6], cmap=cmap, extend='both')
plt.plot(x, y,'k.')
plt.xlabel('x',fontsize=16)
plt.ylabel('y',fontsize=16)
plt.show()
As far as extending the colours beyond what they are now...you'd get a result that would look very different from the main area and would likely have little meaning. If this were a GIS application, I would have those exterior pixels to be "NODATA".
EDIT:
Providing evidence that filling the exterior would look strange...
Using a canned gdal method to fill nodatas, this is what it would look like:
This was quick and dirty and other methods likely exist but would probably look equally odd. Perhaps numpy.nan_to_num is another solution if you don't have gdal.
In case you're curious...here's the code (continues from previous code block):
import gdal
ds = gdal.GetDriverByName('MEM').Create('', zi.shape[1], zi.shape[0], 1, gdal.GDT_Float32)
in_band = ds.GetRasterBand(1)
in_band.SetNoDataValue(-9999)
in_band.FlushCache()
raster_data = np.copy(zi)
raster_data[np.isnan(zi)] = -9999
in_band.WriteArray(raster_data)
#this line takes a while to run...grab a coffee
result = gdal.FillNodata(in_band, None, maxSearchDist=20000, smoothingIterations=0)
in_band.FlushCache()
newz = in_band.ReadAsArray()
fig = plt.figure()
ax = fig.add_subplot(111)
ax.axis((x.min(), x.max(), y.min(), y.max()))
#added the 'extend' parameter as per documentation of plt.contourf
#https://matplotlib.org/3.1.1/api/_as_gen/matplotlib.pyplot.contourf.html
plt.contourf(xi, yi, newz, levels=[1,2,3,4,5,6], cmap=cmap, extend='both')
plt.plot(x, y,'k.')
plt.xlabel('x',fontsize=16)
plt.ylabel('y',fontsize=16)
plt.show()

import matplotlib
colors = ['red','green','blue','purple','black', 'coral']
fig = plt.figure(figsize=(8,8))
plt.scatter(x, y, c = z, cmap=matplotlib.colors.ListedColormap(colors))
plt.show()

looking at df.describe():
id Y X cluster
count 706.000000 706.000000 706.000000 706.000000
mean 357.035411 18401.784703 3217.385269 3.002833
std 205.912934 46147.403750 950.665697 0.532616
min 1.000000 278.000000 328.000000 1.000000
25% 178.500000 3546.000000 2498.500000 3.000000
50% 358.500000 6869.500000 3574.000000 3.000000
75% 534.750000 17169.000000 3997.500000 3.000000
max 712.000000 877392.000000 4321.000000 6.000000
X is between 328 and 4321, Y is between 278 and 887392.
your lines
xi = yi = np.arange(0, 1.01, 0.01)
xi, yi = np.meshgrid(xi,yi)
create a grid with x,y values between zero and one.
So, you are trying to interpolate using data that is very far away from your grid.
Setting
xi = np.arange(0, np.max(x), 0.1)
yi = np.arange(0, np.max(y), 0.1)
xi, yi = np.meshgrid(xi,yi)
and leaving out the np.arange...in plt.contour:
fig = plt.figure()
ax = fig.add_subplot(111)
ax.axis((x.min(), x.max(), y.min(), y.max()))
plt.contourf(xi, yi, zi, cmap='coolwarm') # <-- removed np.arange()
plt.plot(x,y,'k.')
plt.xlabel('x',fontsize=16)
plt.ylabel('y',fontsize=16)
plt.show()
using levels to draw contours:
plt.contourf(xi, yi, zi, levels=[1,2,3,4,5,6], cmap='coolwarm')

Related

How to remove the rectagular white colored frame from my ax.pcolormesh() density plot?

from mplsoccer.pitch import Pitch
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
from scipy.stats import kde
np.random.seed(19680801)
plt.style.use('dark_background')
fields = ['id', 'minute', 'result', 'X1', 'Y','xG','h_a','situation','season',
'shotType','X']
df=pd.read_csv('shots.csv', skipinitialspace=True, usecols=fields)
df1 = pd.DataFrame({'A':df.Y,'B':df.X} )
a=(df1.to_numpy())
x, y = a.T
k = kde.gaussian_kde(a.T)
nbins=50
xi, yi = np.mgrid[x.min():x.max():nbins*1j, y.min():y.max():nbins*1j]
zi = k(np.vstack([xi.flatten(), yi.flatten()]))
pitch = Pitch(orientation='vertical',pitch_type='metricasports', view='half',
linewidth=2, line_zorder=1,
line_color= '#94A7AE',pitch_length=105, pitch_width=68,pad_bottom=0)
fig, ax = pitch.draw()
ax.pcolormesh(xi, yi, zi.reshape(xi.shape), shading='gouraud', cmap='Reds',facecolor='black'
)
ax.set_xlim(ax.get_xlim()[::-1])
ax.yaxis.tick_right()
plt.axis('off')
plt.show()
Output Plot here
I want the only red-colored density plot, not the white rectangular background frame. How to make the frame the same as my background?
Here is an approach using a colormap with an "under" color of 'none'. By setting vmin to a cut-off value, the cells with a lower value will get the "under" color ('none' stands for fully transparent). To get an idea of the values, temporarily a colorbar can be added. The values depend strongly on the extension of the x and y values (the integral of the kde is 1, so over a small domain the values need to be high enough).
from mplsoccer.pitch import Pitch
import numpy as np
import matplotlib.pyplot as plt
from scipy.stats import kde
from copy import copy
np.random.seed(19680801)
plt.style.use('dark_background')
# first create some random toy data roughly mimicking the given plot
x = np.random.randn(100, 20).cumsum(axis=0).flatten()
y = np.random.randn(100, 20).cumsum(axis=0).flatten()
x = x * 0.04 + 0.5
y = y * 0.01 + 0.9
k = kde.gaussian_kde([x, y])
nbins = 50
xi, yi = np.mgrid[x.min():x.max():nbins * 1j, y.min():y.max():nbins * 1j]
zi = k(np.vstack([xi.flatten(), yi.flatten()]))
pitch = Pitch(orientation='vertical', pitch_type='metricasports', view='half',
linewidth=2, line_zorder=1,
line_color='#94A7AE', pitch_length=105, pitch_width=68, pad_bottom=0)
fig, ax = pitch.draw()
cmap = copy(plt.get_cmap('Reds'))
cmap.set_under('none')
pmesh = ax.pcolormesh(xi, yi, zi.reshape(xi.shape), shading='gouraud', cmap=cmap, vmin=5, facecolor='black')
# fig.colorbar(pmesh, ax=ax) # to temporarily get an idea of the values
ax.invert_xaxis()
ax.yaxis.tick_right()
plt.axis('off')
plt.show()

Pcolormesh is not taking right coordinates

pcolormesh plots only exterior coordinates, required plot is
newPress=[22.640048521269733, 8.7880990280388946, 8.5228130097742358, 6.1368312788828003, -0.012232139892299099,
-0.0085282865280444931, 1.4163311525005766, 0.62047309770660242, 14.472422590937441, 15.268280645731416,
17.653997267541644, 24.760479124815305, 22.374762503005076, 22.640048521269733]
poly3[0]=(-15.394, -15.394, -14.394, -14.394, 8.784995481927707, 12.394, 12.394, 15.394, 15.394,
12.394, 12.394, -14.394, -14.394, -15.394)
poly3[1]=(13.0625, -13.0625, -13.0625, -17.5625, -17.5625, -15.74980786686838,
-13.0625, -13.0625, 13.0625, 13.0625, 17.562, 17.562, 13.0625, 13.0625)
numcols, numrows = 200, 200
xi = np.linspace(min(poly3[0]), max(poly3[0]), numcols)
yi = np.linspace(min(poly3[1]), max(poly3[1]), numrows)
xi, yi = np.meshgrid(xi, yi)
x, y, z = poly3[0], poly3[1], newPress
zi = griddata(x, y, z, xi, yi,interp='linear')
fig2 = plt.figure(figsize=(8, 3.5))
ax2 = fig2.add_subplot(111)
ax2.scatter(x,y)
m = plt.pcolormesh(xi, yi, zi, alpha=0.15, cmap='viridis_r')
plt.show()
Judging from this part of the scipy.interpolate.griddata documentation, griddata appears to interpolate on a convex hull around your data points:
fill_value : float, optional Value used to fill in for requested
points outside of the convex hull of the input points. If not
provided, then the default is nan. This option has no effect for the
‘nearest’ method.
This means that you always will get data also outside of the points you provide to griddata. In order to not show these areas, you can set the according points to an invalid (np.nan) value. In your case this is pretty simple.
from matplotlib import pyplot as plt
from scipy.interpolate import griddata
import numpy as np
newPress=np.asarray([22.640048521269733, 8.7880990280388946, 8.5228130097742358, 6.1368312788828003, -0.012232139892299099,
-0.0085282865280444931, 1.4163311525005766, 0.62047309770660242, 14.472422590937441, 15.268280645731416,
17.653997267541644, 24.760479124815305, 22.374762503005076, 22.640048521269733])
poly3 = np.asarray([
(
-15.394, -15.394, -14.394, -14.394, 8.784995481927707,
12.394, 12.394, 15.394, 15.394, 12.394, 12.394, -14.394,
-14.394, -15.394
),
(
13.0625, -13.0625, -13.0625, -17.5625, -17.5625, -15.74980786686838,
-13.0625, -13.0625, 13.0625, 13.0625, 17.562, 17.562, 13.0625, 13.0625
)
])
numcols, numrows = 200, 200
xi = np.linspace(min(poly3[0]), max(poly3[0]), numcols)
yi = np.linspace(min(poly3[1]), max(poly3[1]), numrows)
x, y, z = poly3[0], poly3[1], newPress
xi, yi = np.meshgrid(xi, yi)
zi = griddata(poly3.T,z.T,np.asarray([xi,yi]).T, method='linear').T
fig2 = plt.figure(figsize=(8, 3.5))
ax2 = fig2.add_subplot(111)
ax2.scatter(x,y)
##finding the corners:
ll,lr,ur,ul = zip(x[[2,6,9,12]],y[[2,6,9,12]])
##removing data:
zi[np.logical_and(xi<ll[0],yi<ll[1])] = np.nan
zi[np.logical_and(xi>lr[0],yi<lr[1])] = np.nan
zi[np.logical_and(xi>ur[0],yi>ur[1])] = np.nan
zi[np.logical_and(xi<ul[0],yi>ul[1])] = np.nan
m = ax2.pcolormesh(xi, yi, zi, alpha=0.15, cmap='viridis_r')
plt.show()
The result looks like this:
Please note that your example code was not runnable and needed quite some adjustment. Please, next time when you ask a question, make sure that your code is a Minimal, Complete, and Verifiable example.
EDIT:
For arbitrarily shaped polygons, you can use the technique I outlined here, where you define a path that is composed of your polygon and the outline of the plot area, which you then overlay over your pcolormesh plot with a white color. Note that, in order for this to work properly, your polygon edges have to be ordered correctly along the outline of the polygon (I indicated this in the left subplot in the figure below). In the example below, the edges are ordered in a mathematically positive sense (counter-clockwise) and the edges of the plot area are ordered in the opposite way (clockwise):
from matplotlib import pyplot as plt
from scipy.interpolate import griddata
import numpy as np
from matplotlib.patches import Path, PathPatch
##generate an example polygon:
n_edges = 10
x_max = 15
y_max = 15
##note the sorting of the theta values
thetas = 2*np.pi*np.sort(np.random.rand(n_edges))
radii = 0.5*(np.random.rand(len(thetas))+1)
x = np.cos(thetas)*x_max*radii
y = np.sin(thetas)*y_max*radii
values = np.random.rand(len(thetas))
fig, axes = plt.subplots(ncols=2)
##visualisation
axes[0].quiver(
x[:-1],y[:-1],x[1:]-x[:-1],y[1:]-y[:-1],
scale_units='xy',angles='xy',scale=1,
lw = 3
)
axes[0].scatter(x,y,c=values,zorder=10,cmap='viridis_r')
##interpolation:
numcols, numrows = 200, 200
xi = np.linspace(min(x), max(x), numcols)
yi = np.linspace(min(y), max(y), numrows)
z = values
poly3 = np.asarray([x,y])
xi, yi = np.meshgrid(xi, yi)
zi = griddata(poly3.T,z.T,np.asarray([xi,yi]).T, method='linear').T
axes[1].scatter(x,y, zorder=10)
m = axes[1].pcolormesh(xi, yi, zi, alpha=0.15, cmap='viridis_r',zorder=8)
##getting the limits of the map:
x0,x1 = axes[1].get_xlim()
y0,y1 = axes[1].get_ylim()
map_edges = np.array([[x0,y0],[x0,y1],[x1,y1],[x1,y0]])
##masking the outsides of the polygon
mask = [map_edges,poly3.T]
codes = [[Path.MOVETO] + [Path.LINETO for p in m[1:]] for m in mask]
codes = np.concatenate(codes)
verts = np.concatenate(mask)
path = Path(verts,codes)
patch = PathPatch(path,facecolor='white', lw=0,zorder=9)
axes[1].add_patch(patch)
plt.show()
The result looks something like this:

Pcolormesh not getting correct position matplotlib

I'm plotting data on top of a png image with this 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)
im = plt.imread('statszone_football_pitch.png')
ax1.imshow(im, extent=[0, 740, 0, 515], aspect='auto')
Here is the result:
Pcolormesh should be over the whole image, but it is not. How can i set the correct position?
Why i get smaller pcolormesh respect of whole pitch? I should have something like this (even if this refers to contourf):
Your code seems to work fine. The problem is that what represents your x-axis in the image is not what you giving as x-axis in the plot. That said if you change x to y (and vice-versa) you'll obtain the correct plot:
from scipy.stats.kde import gaussian_kde
import matplotlib.pyplot as plt
import numpy as np
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]
xi, yi = np.mgrid[y.min():y.max():y.size**0.5*1j,x.min():x.max():x.size**0.5*1j] # Changed this.
#zi = k(np.vstack([xi.flatten(), yi.flatten()]))
zi = k(np.vstack([yi.flatten(),xi.flatten()])) # And this.
fig = plt.figure(figsize=(9,10))
ax1 = fig.add_subplot(111)
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)
im = plt.imread('statszone_football_pitch.jpg')
ax1.imshow(im, extent=[0, 740, 0, 515], aspect='auto')
plt.show()
The result is this:
I guess it's a kind of density plot for your scattered points.

convert a scatter plot into a contour plot in matplotllib [duplicate]

I'd like to make a scatter plot where each point is colored by the spatial density of nearby points.
I've come across a very similar question, which shows an example of this using R:
R Scatter Plot: symbol color represents number of overlapping points
What's the best way to accomplish something similar in python using matplotlib?
In addition to hist2d or hexbin as #askewchan suggested, you can use the same method that the accepted answer in the question you linked to uses.
If you want to do that:
import numpy as np
import matplotlib.pyplot as plt
from scipy.stats import gaussian_kde
# Generate fake data
x = np.random.normal(size=1000)
y = x * 3 + np.random.normal(size=1000)
# Calculate the point density
xy = np.vstack([x,y])
z = gaussian_kde(xy)(xy)
fig, ax = plt.subplots()
ax.scatter(x, y, c=z, s=100)
plt.show()
If you'd like the points to be plotted in order of density so that the densest points are always on top (similar to the linked example), just sort them by the z-values. I'm also going to use a smaller marker size here as it looks a bit better:
import numpy as np
import matplotlib.pyplot as plt
from scipy.stats import gaussian_kde
# Generate fake data
x = np.random.normal(size=1000)
y = x * 3 + np.random.normal(size=1000)
# Calculate the point density
xy = np.vstack([x,y])
z = gaussian_kde(xy)(xy)
# Sort the points by density, so that the densest points are plotted last
idx = z.argsort()
x, y, z = x[idx], y[idx], z[idx]
fig, ax = plt.subplots()
ax.scatter(x, y, c=z, s=50)
plt.show()
Plotting >100k data points?
The accepted answer, using gaussian_kde() will take a lot of time. On my machine, 100k rows took about 11 minutes. Here I will add two alternative methods (mpl-scatter-density and datashader) and compare the given answers with same dataset.
In the following, I used a test data set of 100k rows:
import matplotlib.pyplot as plt
import numpy as np
# Fake data for testing
x = np.random.normal(size=100000)
y = x * 3 + np.random.normal(size=100000)
Output & computation time comparison
Below is a comparison of different methods.
1: mpl-scatter-density
Installation
pip install mpl-scatter-density
Example code
import mpl_scatter_density # adds projection='scatter_density'
from matplotlib.colors import LinearSegmentedColormap
# "Viridis-like" colormap with white background
white_viridis = LinearSegmentedColormap.from_list('white_viridis', [
(0, '#ffffff'),
(1e-20, '#440053'),
(0.2, '#404388'),
(0.4, '#2a788e'),
(0.6, '#21a784'),
(0.8, '#78d151'),
(1, '#fde624'),
], N=256)
def using_mpl_scatter_density(fig, x, y):
ax = fig.add_subplot(1, 1, 1, projection='scatter_density')
density = ax.scatter_density(x, y, cmap=white_viridis)
fig.colorbar(density, label='Number of points per pixel')
fig = plt.figure()
using_mpl_scatter_density(fig, x, y)
plt.show()
Drawing this took 0.05 seconds:
And the zoom-in looks quite nice:
2: datashader
Datashader is an interesting project. It has added support for matplotlib in datashader 0.12.
Installation
pip install datashader
Code (source & parameterer listing for dsshow):
import datashader as ds
from datashader.mpl_ext import dsshow
import pandas as pd
def using_datashader(ax, x, y):
df = pd.DataFrame(dict(x=x, y=y))
dsartist = dsshow(
df,
ds.Point("x", "y"),
ds.count(),
vmin=0,
vmax=35,
norm="linear",
aspect="auto",
ax=ax,
)
plt.colorbar(dsartist)
fig, ax = plt.subplots()
using_datashader(ax, x, y)
plt.show()
It took 0.83 s to draw this:
There is also possibility to colorize by third variable. The third parameter for dsshow controls the coloring. See more examples here and the source for dsshow here.
3: scatter_with_gaussian_kde
def scatter_with_gaussian_kde(ax, x, y):
# https://stackoverflow.com/a/20107592/3015186
# Answer by Joel Kington
xy = np.vstack([x, y])
z = gaussian_kde(xy)(xy)
ax.scatter(x, y, c=z, s=100, edgecolor='')
It took 11 minutes to draw this:
4: using_hist2d
import matplotlib.pyplot as plt
def using_hist2d(ax, x, y, bins=(50, 50)):
# https://stackoverflow.com/a/20105673/3015186
# Answer by askewchan
ax.hist2d(x, y, bins, cmap=plt.cm.jet)
It took 0.021 s to draw this bins=(50,50):
It took 0.173 s to draw this bins=(1000,1000):
Cons: The zoomed-in data does not look as good as in with mpl-scatter-density or datashader. Also you have to determine the number of bins yourself.
5: density_scatter
The code is as in the answer by Guillaume.
It took 0.073 s to draw this with bins=(50,50):
It took 0.368 s to draw this with bins=(1000,1000):
Also, if the number of point makes KDE calculation too slow, color can be interpolated in np.histogram2d [Update in response to comments: If you wish to show the colorbar, use plt.scatter() instead of ax.scatter() followed by plt.colorbar()]:
import numpy as np
import matplotlib.pyplot as plt
from matplotlib import cm
from matplotlib.colors import Normalize
from scipy.interpolate import interpn
def density_scatter( x , y, ax = None, sort = True, bins = 20, **kwargs ) :
"""
Scatter plot colored by 2d histogram
"""
if ax is None :
fig , ax = plt.subplots()
data , x_e, y_e = np.histogram2d( x, y, bins = bins, density = True )
z = interpn( ( 0.5*(x_e[1:] + x_e[:-1]) , 0.5*(y_e[1:]+y_e[:-1]) ) , data , np.vstack([x,y]).T , method = "splinef2d", bounds_error = False)
#To be sure to plot all data
z[np.where(np.isnan(z))] = 0.0
# Sort the points by density, so that the densest points are plotted last
if sort :
idx = z.argsort()
x, y, z = x[idx], y[idx], z[idx]
ax.scatter( x, y, c=z, **kwargs )
norm = Normalize(vmin = np.min(z), vmax = np.max(z))
cbar = fig.colorbar(cm.ScalarMappable(norm = norm), ax=ax)
cbar.ax.set_ylabel('Density')
return ax
if "__main__" == __name__ :
x = np.random.normal(size=100000)
y = x * 3 + np.random.normal(size=100000)
density_scatter( x, y, bins = [30,30] )
You could make a histogram:
import numpy as np
import matplotlib.pyplot as plt
# fake data:
a = np.random.normal(size=1000)
b = a*3 + np.random.normal(size=1000)
plt.hist2d(a, b, (50, 50), cmap=plt.cm.jet)
plt.colorbar()

Contour graph in python

How would I make a countour grid in python using matplotlib.pyplot, where the grid is one colour where the z variable is below zero and another when z is equal to or larger than zero? I'm not very familiar with matplotlib so if anyone can give me a simple way of doing this, that would be great.
So far I have:
x= np.arange(0,361)
y= np.arange(0,91)
X,Y = np.meshgrid(x,y)
area = funcarea(L,D,H,W,X,Y) #L,D,H and W are all constants defined elsewhere.
plt.figure()
plt.contourf(X,Y,area)
plt.show()
You can do this using the levels keyword in contourf.
import numpy as np
import matplotlib.pyplot as plt
fig, axs = plt.subplots(1,2)
x = np.linspace(0, 1, 100)
X, Y = np.meshgrid(x, x)
Z = np.sin(X)*np.sin(Y)
levels = np.linspace(-1, 1, 40)
zdata = np.sin(8*X)*np.sin(8*Y)
cs = axs[0].contourf(X, Y, zdata, levels=levels)
fig.colorbar(cs, ax=axs[0], format="%.2f")
cs = axs[1].contourf(X, Y, zdata, levels=[-1,0,1])
fig.colorbar(cs, ax=axs[1])
plt.show()
You can change the colors by choosing and different colormap; using vmin, vmax; etc.

Categories

Resources