speed=[0.129438,0.0366483,0.439946,0.090253,0.19373,0.592419,0.00903306,0.520847,0.513714,1.16971,5.12548,4.37745,3.2362,2.91004,1.60186,0.115595,0.270153,0.19367,0.0865046,0.558443,0.613072,0.648203,0.0770592,0.81772,0.234523,1.04013,0.352675,0.0673293,0.492684,0.109398,0.402816,0.140199,0.998795,0.367604,0.52436,0.0968265,1.59786,2.43149,2.94133,0.940624,0.257224,0,0,0.0199409,0.125302,0,0.367911,0.259797,0.237776,0.45428,0.507738,0.389389,0.388758,0.335398,0.510133,0.180295,0.0738368,0.780367,0.925679,1.93922,1.96569,1.39523,0.824564,0.00833059,0,0.0498536,0.112622,0,0.00843256,0.0269059,0.00816307,0.0582206,0.578959,1.0171,2.24302,1.92721]
direction=[189.538,215.866,264.086,135.325,165.893,44.2853,136.158,350.437,83.2484,277.783,288.064,279.222,267.214,265.913,235.173,181.206,136.14,144.281,134.581,108.16,75.4158,22.2881,328.882,68.3736,129.256,278.097,326.581,35.7096,321.297,338.31,354.109,24.1976,38.1465,39.2318,63.8145,119.817,186.106,182.673,185.475,173.223,139.843,np.nan,np.nan,40.9179,320.081,np.nan,333.054,354.726,357.716,18.1253,355.461,286.084,319.073,324.621,339.681,313.331,346.647,84.9661,86.7814,88.5452,104.456,128.953,87.5388,72.1999,np.nan,345.5,356.68,np.nan,316.586,338.82,334.731,98.3435,85.669,25.9086,42.6986,34.4194]
gas=[1.10986,1.25806,1.50921,1.37323,1.41317,1.15709,1.16005,1.43474,1.43952,1.03368,0.246893,0.139811,0.15603,0.203752,0.177984,0.164834,0.528146,0.602864,0.809435,1.0036,1.05669,1.05348,0.988772,1.0588,1.12066,1.15746,1.23219,1.142,1.21676,1.27093,1.00094,1.16773,1.16163,1.1715,0.999969,0.863695,0.832681,0.92631,1.01416,1.02708,1.0084,1.00666,1.06311,1.32098,1.48134,1.60667,1.60324,1.58663,1.41159,1.3251,1.25114,1.24269,1.16683,1.20762,1.0616,1.21975,1.21312,1.11416,0.981076,0.707948,0.590113,0.515484,0.417111,0.436767,0.644229,0.998097,1.24321,1.45975,1.3905,1.50087,1.63685,1.53855,1.21446,1.09367,0.790929,0.693877]
I know it has to be np.meshgrid(direction,speed) firstly, but the var of 'gas' I don't know to how to matching direction and speed so that I can plot a windrose map. Just like a image from a paper I read as follow.
I really appreciate for any help or suggestion.
You might be interested in the Windrose library for some options to create this kind of plots, for example a polar filled contour plot.
Alternatively, here is an approach with small 2D regions in a polar plot:
import matplotlib.pyplot as plt
import numpy as np
from scipy import interpolate
speed = [0.129438, 0.0366483, 0.439946, 0.090253, 0.19373, 0.592419, 0.00903306, 0.520847, 0.513714, 1.16971, 5.12548, 4.37745, 3.2362, 2.91004, 1.60186, 0.115595, 0.270153, 0.19367, 0.0865046, 0.558443, 0.613072, 0.648203, 0.0770592, 0.81772, 0.234523, 1.04013, 0.352675, 0.0673293, 0.492684, 0.109398, 0.402816, 0.140199, 0.998795, 0.367604, 0.52436, 0.0968265, 1.59786, 2.43149, 2.94133, 0.940624, 0.257224, 0, 0, 0.0199409, 0.125302, 0, 0.367911, 0.259797, 0.237776, 0.45428, 0.507738, 0.389389, 0.388758, 0.335398, 0.510133, 0.180295, 0.0738368, 0.780367, 0.925679, 1.93922, 1.96569, 1.39523, 0.824564, 0.00833059, 0, 0.0498536, 0.112622, 0, 0.00843256, 0.0269059, 0.00816307, 0.0582206, 0.578959, 1.0171, 2.24302, 1.92721]
direction = [189.538, 215.866, 264.086, 135.325, 165.893, 44.2853, 136.158, 350.437, 83.2484, 277.783, 288.064, 279.222, 267.214, 265.913, 235.173, 181.206, 136.14, 144.281, 134.581, 108.16, 75.4158, 22.2881, 328.882, 68.3736, 129.256, 278.097, 326.581, 35.7096, 321.297, 338.31, 354.109, 24.1976, 38.1465, 39.2318, 63.8145, 119.817, 186.106, 182.673, 185.475, 173.223, 139.843, np.nan, np.nan, 40.9179, 320.081, np.nan, 333.054, 354.726, 357.716, 18.1253, 355.461, 286.084, 319.073, 324.621, 339.681, 313.331, 346.647, 84.9661, 86.7814, 88.5452, 104.456, 128.953, 87.5388, 72.1999, np.nan, 345.5, 356.68, np.nan, 316.586, 338.82, 334.731, 98.3435, 85.669, 25.9086, 42.6986, 34.4194]
gas = [1.10986, 1.25806, 1.50921, 1.37323, 1.41317, 1.15709, 1.16005, 1.43474, 1.43952, 1.03368, 0.246893, 0.139811, 0.15603, 0.203752, 0.177984, 0.164834, 0.528146, 0.602864, 0.809435, 1.0036, 1.05669, 1.05348, 0.988772, 1.0588, 1.12066, 1.15746, 1.23219, 1.142, 1.21676, 1.27093, 1.00094, 1.16773, 1.16163, 1.1715, 0.999969, 0.863695, 0.832681, 0.92631, 1.01416, 1.02708, 1.0084, 1.00666, 1.06311, 1.32098, 1.48134, 1.60667, 1.60324, 1.58663, 1.41159, 1.3251, 1.25114, 1.24269, 1.16683, 1.20762, 1.0616, 1.21975, 1.21312, 1.11416, 0.981076, 0.707948, 0.590113, 0.515484, 0.417111, 0.436767, 0.644229, 0.998097, 1.24321, 1.45975, 1.3905, 1.50087, 1.63685, 1.53855, 1.21446, 1.09367, 0.790929, 0.693877]
dir_rad = np.radians(np.array(direction))
speed = np.array(speed)
gas = np.array(gas)
WD, WS = np.meshgrid(np.linspace(0, 2 * np.pi, 37), np.linspace(min(speed), max(speed), 16))
filter = np.isfinite(dir_rad)
Z = interpolate.griddata((dir_rad[filter], speed[filter]), gas[filter], (WD, WS), method='linear')
fig, ax = plt.subplots(subplot_kw={"projection": "polar"})
cmap = plt.get_cmap('inferno')
img = ax.pcolormesh(WD, WS, Z, cmap=cmap)
plt.colorbar(img)
plt.show()
PS: Try to avoid the 'jet' colormap, as it creates a yellow highlight at the wrong spots.
Here is another approach, using hist2d, which doesn't interpolate the values over larger regions:
import matplotlib.pyplot as plt
import numpy as np
speed = [0.129438, 0.0366483, 0.439946, 0.090253, 0.19373, 0.592419, 0.00903306, 0.520847, 0.513714, 1.16971, 5.12548, 4.37745, 3.2362, 2.91004, 1.60186, 0.115595, 0.270153, 0.19367, 0.0865046, 0.558443, 0.613072, 0.648203, 0.0770592, 0.81772, 0.234523, 1.04013, 0.352675, 0.0673293, 0.492684, 0.109398, 0.402816, 0.140199, 0.998795, 0.367604, 0.52436, 0.0968265, 1.59786, 2.43149, 2.94133, 0.940624, 0.257224, 0, 0, 0.0199409, 0.125302, 0, 0.367911, 0.259797, 0.237776, 0.45428, 0.507738, 0.389389, 0.388758, 0.335398, 0.510133, 0.180295, 0.0738368, 0.780367, 0.925679, 1.93922, 1.96569, 1.39523, 0.824564, 0.00833059, 0, 0.0498536, 0.112622, 0, 0.00843256, 0.0269059, 0.00816307, 0.0582206, 0.578959, 1.0171, 2.24302, 1.92721]
direction = [189.538, 215.866, 264.086, 135.325, 165.893, 44.2853, 136.158, 350.437, 83.2484, 277.783, 288.064, 279.222, 267.214, 265.913, 235.173, 181.206, 136.14, 144.281, 134.581, 108.16, 75.4158, 22.2881, 328.882, 68.3736, 129.256, 278.097, 326.581, 35.7096, 321.297, 338.31, 354.109, 24.1976, 38.1465, 39.2318, 63.8145, 119.817, 186.106, 182.673, 185.475, 173.223, 139.843, np.nan, np.nan, 40.9179, 320.081, np.nan, 333.054, 354.726, 357.716, 18.1253, 355.461, 286.084, 319.073, 324.621, 339.681, 313.331, 346.647, 84.9661, 86.7814, 88.5452, 104.456, 128.953, 87.5388, 72.1999, np.nan, 345.5, 356.68, np.nan, 316.586, 338.82, 334.731, 98.3435, 85.669, 25.9086, 42.6986, 34.4194]
gas = [1.10986, 1.25806, 1.50921, 1.37323, 1.41317, 1.15709, 1.16005, 1.43474, 1.43952, 1.03368, 0.246893, 0.139811, 0.15603, 0.203752, 0.177984, 0.164834, 0.528146, 0.602864, 0.809435, 1.0036, 1.05669, 1.05348, 0.988772, 1.0588, 1.12066, 1.15746, 1.23219, 1.142, 1.21676, 1.27093, 1.00094, 1.16773, 1.16163, 1.1715, 0.999969, 0.863695, 0.832681, 0.92631, 1.01416, 1.02708, 1.0084, 1.00666, 1.06311, 1.32098, 1.48134, 1.60667, 1.60324, 1.58663, 1.41159, 1.3251, 1.25114, 1.24269, 1.16683, 1.20762, 1.0616, 1.21975, 1.21312, 1.11416, 0.981076, 0.707948, 0.590113, 0.515484, 0.417111, 0.436767, 0.644229, 0.998097, 1.24321, 1.45975, 1.3905, 1.50087, 1.63685, 1.53855, 1.21446, 1.09367, 0.790929, 0.693877]
dir_rad = np.radians(np.array(direction))
speed = np.array(speed)
gas = np.array(gas)
fig, axes = plt.subplots(ncols=2, figsize=(10, 4), subplot_kw={"projection": "polar"})
cmap = 'inferno_r'
for ax in axes:
if ax == axes[1]:
vals, _, _, img = ax.hist2d(dir_rad, speed,
bins=(np.linspace(0, 2 * np.pi, 37), np.linspace(min(speed), max(speed), 16)),
weights=gas, cmap=cmap, vmin=0, vmax=max(gas) * 1.1, cmin=0.00001)
else:
img = ax.scatter(dir_rad, speed, c=gas, cmap=cmap, vmin=0, vmax=max(gas) * 1.1)
# ax.set_theta_zero_location('N')
# ax.set_theta_direction(-1)
plt.colorbar(img, ax=ax, pad=0.12)
plt.show()
Try polar scatter plot:
import numpy as np
import matplotlib.pyplot as plt
speed=[0.129438,0.0366483,0.439946,0.090253,0.19373,0.592419,0.00903306,0.520847,0.513714,1.16971,5.12548,4.37745,3.2362,2.91004,1.60186,0.115595,0.270153,0.19367,0.0865046,0.558443,0.613072,0.648203,0.0770592,0.81772,0.234523,1.04013,0.352675,0.0673293,0.492684,0.109398,0.402816,0.140199,0.998795,0.367604,0.52436,0.0968265,1.59786,2.43149,2.94133,0.940624,0.257224,0,0,0.0199409,0.125302,0,0.367911,0.259797,0.237776,0.45428,0.507738,0.389389,0.388758,0.335398,0.510133,0.180295,0.0738368,0.780367,0.925679,1.93922,1.96569,1.39523,0.824564,0.00833059,0,0.0498536,0.112622,0,0.00843256,0.0269059,0.00816307,0.0582206,0.578959,1.0171,2.24302,1.92721]
direction=[189.538,215.866,264.086,135.325,165.893,44.2853,136.158,350.437,83.2484,277.783,288.064,279.222,267.214,265.913,235.173,181.206,136.14,144.281,134.581,108.16,75.4158,22.2881,328.882,68.3736,129.256,278.097,326.581,35.7096,321.297,338.31,354.109,24.1976,38.1465,39.2318,63.8145,119.817,186.106,182.673,185.475,173.223,139.843,np.nan,np.nan,40.9179,320.081,np.nan,333.054,354.726,357.716,18.1253,355.461,286.084,319.073,324.621,339.681,313.331,346.647,84.9661,86.7814,88.5452,104.456,128.953,87.5388,72.1999,np.nan,345.5,356.68,np.nan,316.586,338.82,334.731,98.3435,85.669,25.9086,42.6986,34.4194]
gas=[1.10986,1.25806,1.50921,1.37323,1.41317,1.15709,1.16005,1.43474,1.43952,1.03368,0.246893,0.139811,0.15603,0.203752,0.177984,0.164834,0.528146,0.602864,0.809435,1.0036,1.05669,1.05348,0.988772,1.0588,1.12066,1.15746,1.23219,1.142,1.21676,1.27093,1.00094,1.16773,1.16163,1.1715,0.999969,0.863695,0.832681,0.92631,1.01416,1.02708,1.0084,1.00666,1.06311,1.32098,1.48134,1.60667,1.60324,1.58663,1.41159,1.3251,1.25114,1.24269,1.16683,1.20762,1.0616,1.21975,1.21312,1.11416,0.981076,0.707948,0.590113,0.515484,0.417111,0.436767,0.644229,0.998097,1.24321,1.45975,1.3905,1.50087,1.63685,1.53855,1.21446,1.09367,0.790929,0.693877]
gas = [g * 100 for g in gas]
fig = plt.figure()
ax = fig.add_subplot(111, projection='polar')
c = ax.scatter(direction, speed, c=direction, s=gas, cmap='hsv', alpha=0.25)
result:
I multiplied gas by 10 to make points bigger, but you may adjust it as You need,
as well as lists/variables to axis assigment and rotation of coordinate system.
I have written some code to plot the longitude and latitude of towns/cities in the UK with the 3D bar height representing the population of these places. I am trying to also colour code the bars using a colormap so that the variation in population can be more easily seen. However, my code doesnt seem to follow the colormap and instead all the bars have very similar colours - I am not sure where I have gone wrong
from mpl_toolkits.mplot3d import Axes3D
import matplotlib.pyplot as plt
import numpy as np
pop = [189120, 91297, 107123, 107355, 94782, 87590, 142968, 1085810, 117963, 147663, 194189, 187503, 349561, 229700, 535907, 145818, 335145, 110507, 116447, 86011, 88483, 119441, 325949, 106943, 92363, 255394, 109805, 144170, 109185, 468720, 113507, 120046, 104157, 589900, 136362, 88243, 88134, 88855, 91053, 94932, 120256, 162949, 284321, 144957, 474632, 443760, 100160, 552267, 8173941, 211228, 107627, 510746, 174700, 171750, 268064, 128060, 215173, 186682, 289301, 86552, 96555, 159994, 161707, 234982, 154718, 238137, 97886, 95580, 218705, 107926, 109691, 134022, 103886, 518090, 155298, 123187, 253651, 175547, 91703, 102885, 89663, 105878, 270726, 174286, 109015, 179485, 182441, 142723, 99251, 165456, 131982, 91930, 218791, 83641, 103608, 105367, 265178, 100153, 109120, 152841]
lat = [57.14369, 53.55, 51.56844, 51.26249, 51.37795, 52.13459, 53.39337, 52.48142, 53.75, 53.81667, 53.58333, 50.72048, 53.79391, 50.82838, 51.45523, 52.2, 51.48, 51.73575, 51.9, 53.1905, 53.25, 51.88921, 52.40656, 51.11303, 54.52429, 52.92277, 53.52327, 56.5, 50.76871, 55.95206, 50.7236, 54.96209, 51.38914, 55.86515, 51.86568, 53.56539, 53.71667, 54.68611, 50.85519, 51.75369, 51.62907, 53.64904, 53.7446, 52.05917, 53.79648, 52.6386, 53.22683, 53.41058, 51.50853, 51.87967, 51.26667, 53.48095, 54.57623, 52.04172, 54.97328, 51.58774, 52.25, 52.62783, 52.9536, 52.52323, 53.54051, 51.75222, 52.57364, 50.37153, 50.71667, 50.79899, 53.76667, 51.58571, 51.45625, 53.61766, 53.43012, 53.42519, 53.48771, 53.38297, 51.50949, 52.41426, 50.90395, 51.53782, 53.64779, 53.45, 51.90224, 53.40979, 53.00415, 54.90465, 52.56667, 51.62079, 51.55797, 52.67659, 53.68331, 53.39254, 51.65531, 52.51868, 51.50853, 51.34603, 53.53333, 51.31903, 52.58547, 52.18935, 50.81448, 53.95763]
long = [-2.09814, -1.48333, 0.45782, -1.08708, -2.35907, -0.46632, -3.01479, -1.89983, -2.48333, -3.05, -2.43333, -1.8795, -1.75206, -0.13947, -2.59665, 0.11667, -3.18, 0.46958, -2.08333, -2.89189, -1.41667, 0.90421, -1.51217, -0.18312, -1.55039, -1.47663, -1.13691, -2.96667, 0.28453, -3.19648, -3.52751, -1.60168, 0.54863, -4.25763, -2.2431, -0.07553, -1.85, -1.2125, 0.57292, -0.47517, -0.74934, -1.78416, -0.33525, 1.15545, -1.54785, -1.13169, -0.53792, -2.97794, -0.12574, -0.41748, 0.51667, -2.23743, -1.23483, -0.75583, -1.61396, -2.99835, -0.88333, 1.29834, -1.15047, -1.46523, -2.1183, -1.25596, -0.24777, -4.14305, -2.0, -1.09125, -2.71667, 0.60459, -0.97113, -2.1552, -1.35678, -2.32443, -2.29042, -1.4659, -0.59541, -1.78094, -1.40428, 0.71433, -3.00648, -2.73333, -0.20256, -2.15761, -2.18538, -1.38222, -1.81667, -3.94323, -1.78116, -2.44926, -1.49768, -2.58024, -0.39602, -1.9945, -0.12574, -2.97665, -2.61667, -0.55893, -2.12296, -2.22001, -0.37126, -1.08271]
fig = plt.figure()
ax = Axes3D(fig)
X,Y,Z = np.array(long),np.array(lat),np.log10(np.array(pop))
colours = plt.cm.rainbow_r(Z/np.log10(max(pop)))
plot1 = ax.bar3d(X,Y,Z,dx=0.2,dy=0.2,dz=Z/3,color=colours)
ax.set_xlabel('\nLongitude (\u00B0)')
ax.set_ylabel('\nLatitude (\u00B0)')
ax.set_zlabel('\nlog\u2081\u2080(Population)')
ax.set_zlim3d(4,7)
ax.view_init(elev=70,azim=280)
colourMap = plt.cm.ScalarMappable(cmap=plt.cm.rainbow_r)
colourMap.set_array(Z)
colBar = plt.colorbar(colourMap).set_label('log\u2081\u2080(Population)')
plt.show()
The code produces this plot:
I think that the majority of the bars should be red/orange in colour, with only the major cities being yellow/green/blue...
(Z/np.log10(max(pop))).min() is 0.7. So all values are indeed in the upper range of the colormap.
You probably want to normalize your data before giving it to the colormap:
norm = plt.Normalize((Z/np.log10(max(pop))).min(), (Z/np.log10(max(pop))).max())
colours = plt.cm.rainbow_r(norm(Z/np.log10(max(pop))))
I know that there are several similar questions such as Use of curve_fit to fit data but the answer there (specific float type) does not seem to work for me. I am wondering if anyone is able to explain to me why the following code (which is an adaptation from an answer -> https://stackoverflow.com/a/11507723/1093485) does not work.
sample code:
#! /usr/bin/env python
import numpy
from scipy.optimize import curve_fit
import matplotlib.pyplot as plt
def gaussFunction(x, A, mu, sigma):
return A*numpy.exp(-(x-mu)**2/(2.*sigma**2))
x_points = [4245.428, 4245.4378, 4245.4477, 4245.4575, 4245.4673, 4245.4772, 4245.487, 4245.4968, 4245.5066, 4245.5165, 4245.5263, 4245.5361, 4245.546, 4245.5558, 4245.5656, 4245.5755, 4245.5853, 4245.5951, 4245.605, 4245.6148, 4245.6246, 4245.6345, 4245.6443, 4245.6541, 4245.6639, 4245.6738, 4245.6836, 4245.6934, 4245.7033, 4245.7131, 4245.7229, 4245.7328, 4245.7426, 4245.7524, 4245.7623, 4245.7721, 4245.7819, 4245.7918, 4245.8016, 4245.8114, 4245.8213, 4245.8311, 4245.8409, 4245.8508, 4245.8606, 4245.8704, 4245.8803, 4245.8901, 4245.8999, 4245.9097, 4245.9196, 4245.9294, 4245.9392, 4245.9491, 4245.9589, 4245.9687, 4245.9786, 4245.9884, 4245.9982, 4246.0081, 4246.0179, 4246.0277, 4246.0376, 4246.0474, 4246.0572, 4246.0671, 4246.0769, 4246.0867, 4246.0966, 4246.1064, 4246.1162, 4246.1261, 4246.1359, 4246.1457, 4246.1556, 4246.1654, 4246.1752, 4246.1851, 4246.1949, 4246.2047, 4246.2146]
y_points = [978845.0, 1165115.0, 1255368.0, 1253901.0, 1199857.0, 1134135.0, 1065403.0, 977347.0, 866444.0, 759457.0, 693284.0, 679772.0, 696896.0, 706494.0, 668272.0, 555221.0, 374547.0, 189968.0, 161754.0, 216483.0, 181937.0, 73967.0, 146627.0, 263495.0, 284992.0, 240291.0, 327541.0, 555690.0, 758847.0, 848035.0, 800159.0, 645769.0, 444412.0, 249627.0, 125078.0, 254856.0, 498501.0, 757049.0, 977861.0, 1125316.0, 1202892.0, 1263220.0, 1366361.0, 1497071.0, 1559804.0, 1464012.0, 1196896.0, 848736.0, 584363.0, 478640.0, 392943.0, 312466.0, 355540.0, 320666.0, 114711.0, 690948.0, 1409389.0, 1825921.0, 1636486.0, 1730980.0, 4081179.0, 7754166.0, 11747734.0, 15158681.0, 17197366.0, 17388832.0, 15710571.0, 12593935.0, 8784968.0, 5115720.0, 2277684.0, 769734.0, 674437.0, 647250.0, 708156.0, 882759.0, 833756.0, 504655.0, 317790.0, 711106.0, 1011705.0]
# Try to fit the gaussian
trialX = numpy.linspace(x_points[0],x_points[-1],1000)
coeff, var_matrix = curve_fit(gaussFunction, x_points, y_points)
yEXP = gaussFunction(trialX, *coeff)
# Plot the data (just for visualization)
fig = plt.figure()
ax = fig.add_subplot(111)
plt.plot(x_points, y_points, 'b*')
plt.plot(trialX,yEXP, '--')
plt.show()
The output that it generates:
Without starting parameters they default to 1. Putting in
reasonable p0, it works:
p0 = [np.max(y_points), x_points[np.argmax(y_points)], 0.1]
coeff, var_matrix = curve_fit(gaussFunction, x_points, y_points, p0)
Leads to: