5

I have a dataframe consisting of measurements from a particular magnetometer station over time, with columns corresponding to:

  • its latitude (which I think of as a radius)
  • its azimuthal angle
  • a measured quantity at this specific time

I was wondering of a way to plot this dataframe as a polar histogram for the measured variable: ie something like this:

Shi et al, 2018, doi:10.1029/2017JA025033

I have looked at the special histogram in physt but this allows me to only put in x,y values and I'm quite confused by it all.

Could anybody help?

R Thompson
  • 353
  • 3
  • 15
  • Just wanted to say that is a very cool chart – rgk Mar 08 '19 at 13:38
  • Seconding on the cool chart. The closest I've ever encountered is https://matplotlib.org/basemap/users/paeqd.html but I'm not sure it can be stretched for this kind of output – roganjosh Mar 08 '19 at 13:39
  • Are you sure you want a histogram? That seems to contradict the third requirement "a measured quantity at this specific time". Can you clarify what exactly you need? – ImportanceOfBeingErnest Mar 08 '19 at 13:53
  • Essential what I want to show is a certain characteristic of the measured quantity at a specific radius-azimuth bin. So with histogram what I mean is an occurrence number in the specific radius-azimuth bin. Does that help? – R Thompson Mar 08 '19 at 14:20
  • No, it doesn't. It's easy: Do you have 2 columns, `radius` and `azimut`? Then you can plot occurance as histogram. Do you have 3 columns, `radius` and `azimut`, `measured quantity`, then you cannot plot a histogram, but rather the `measured quantity` as a function of the other two. Which one is it? – ImportanceOfBeingErnest Mar 08 '19 at 17:16
  • Right now the first one, and I’ve managed to plot it now. In the future I’ll need to do the second, but I believe in my mind I know how to do that now too – R Thompson Mar 08 '19 at 17:23

2 Answers2

7

Calculating a histogram is easily done with numpy.histogram2d. Plotting the resulting 2D array can be done with matplotlib's pcolormesh.

import numpy as np; np.random.seed(42)
import matplotlib.pyplot as plt

# two input arrays
azimut = np.random.rand(3000)*2*np.pi
radius = np.random.rayleigh(29, size=3000)

# define binning
rbins = np.linspace(0,radius.max(), 30)
abins = np.linspace(0,2*np.pi, 60)

#calculate histogram
hist, _, _ = np.histogram2d(azimut, radius, bins=(abins, rbins))
A, R = np.meshgrid(abins, rbins)

# plot
fig, ax = plt.subplots(subplot_kw=dict(projection="polar"))

pc = ax.pcolormesh(A, R, hist.T, cmap="magma_r")
fig.colorbar(pc)

plt.show()

enter image description here

ImportanceOfBeingErnest
  • 321,279
  • 53
  • 665
  • 712
4

This appears to be what you're looking for: https://physt.readthedocs.io/en/latest/special_histograms.html#Polar-histogram

from physt import histogram, binnings, special
import numpy as np
import matplotlib.pyplot as plt

# Generate some points in the Cartesian coordinates
np.random.seed(42)

x = np.random.rand(1000)
y = np.random.rand(1000)
z = np.random.rand(1000)

# Create a polar histogram with default parameters
hist = special.polar_histogram(x, y)
ax = hist.plot.polar_map()

Polar histogram created with physt

The docs linked include more examples with colors, bin sizing etc.

Edit: I think this is going to take a bit of munging to get your data into the right shape, but I think this example illustrates the library's capabilities and can be adjusted to your use case:

import random
import numpy as np
import matplotlib.pyplot as plt
from physt import special

# Generate some points in the Cartesian coordinates
np.random.seed(42)

gen = lambda l, h, s = 3000: np.asarray([random.random() * (h - l) + l for _ in range(s)])

X = gen(-100, 100)
Y = gen(-1000, 1000)
Z = gen(0, 1400)

hist = special.polar_histogram(X, Y, weights=Z, radial_bins=40)
# ax = hist.plot.polar_map()

hist.plot.polar_map(density=True, show_zero=False, cmap="inferno", lw=0.5, figsize=(5, 5))
plt.show()

Example with color & custom coordinates

rgk
  • 985
  • 8
  • 16
  • This is what I originally tried, but it doesn't allow for any z information as far as I could figure out – R Thompson Mar 08 '19 at 13:40
  • z information as in magnitude? Isn't that just the values in the data? Forgive me if I'm not fully understanding your question – rgk Mar 08 '19 at 13:44
  • I guess for now the values in the data of the measured quantity might not be the most relevant. So forget that apart for now. So I have effectively a time series for r and theta, how would I put that into the function above to get the histogram over the whole azimuthal space? – R Thompson Mar 08 '19 at 13:54
  • Edited my example above - the package receives X & Y as cartesian coordinates, and your polar coodinate data can be transformed to fit the function and produce the chart you want (see more: https://www.math.uh.edu/~mmsosa/Math1330/Calendar/1330Day28.pdf). I used extreme values for Y to illustrate the point, but symmetrically scaled X & Y inputs would produce a radially symmetric chart. – rgk Mar 08 '19 at 15:05