5

I am trying to create a combination of the two images below.

Density Plot

Circular Bar Plot

Basically I want the design of the density plot, but around a circle instead of a normal X/Y chart setup.

Below is the code for the density plot in Python.

    # !pip install brewer2mpl
import numpy as np
import pandas as pd
import matplotlib as mpl
import matplotlib.pyplot as plt
import seaborn as sns
import warnings; warnings.filterwarnings(action='once')

large = 22; med = 16; small = 12
params = {'axes.titlesize': large,
          'legend.fontsize': med,
          'figure.figsize': (16, 10),
          'axes.labelsize': med,
          'axes.titlesize': med,
          'xtick.labelsize': med,
          'ytick.labelsize': med,
          'figure.titlesize': large}
plt.rcParams.update(params)
plt.style.use('seaborn-whitegrid')
sns.set_style("white")
#%matplotlib inline

# Version
print(mpl.__version__)  #> 3.0.0
print(sns.__version__)  #> 0.9.0

# Import Data
df = pd.read_csv("https://github.com/selva86/datasets/raw/master/mpg_ggplot2.csv")

# Draw Plot
plt.figure(figsize=(16,10), dpi= 80)
sns.kdeplot(df.loc[df['cyl'] == 4, "cty"], shade=True, color="g", label="Cyl=4", alpha=.7)
sns.kdeplot(df.loc[df['cyl'] == 5, "cty"], shade=True, color="deeppink", label="Cyl=5", alpha=.7)
sns.kdeplot(df.loc[df['cyl'] == 6, "cty"], shade=True, color="dodgerblue", label="Cyl=6", alpha=.7)
sns.kdeplot(df.loc[df['cyl'] == 8, "cty"], shade=True, color="orange", label="Cyl=8", alpha=.7)

# Decoration
plt.title('Density Plot of City Mileage by n_Cylinders', fontsize=22)
plt.legend()
plt.show()

And here is the code for the Circular Bar Plot.

    import numpy as np
import matplotlib.pyplot as plt

#~~~~~~~~~~~Test~~~~~~~#
import pandas as pd
import seaborn as sns
# Import Data
df = pd.read_csv("https://github.com/selva86/datasets/raw/master/mpg_ggplot2.csv")
#~~~~~~~~~~~Test~~~~~~~#

N = 80
bottom = 8
max_height = 4

theta = np.linspace(0.0, 2 * np.pi, N, endpoint=False)
radii = max_height*np.random.rand(N)
width = (2*np.pi) / N

ax = plt.subplot(111, polar=True)
bars = ax.bar(theta, radii, width=width, bottom=bottom)



# Use custom colors and opacity
for r, bar in zip(radii, bars):
    bar.set_facecolor(plt.cm.jet(r / 10.))
    bar.set_alpha(0.8)

plt.show()

I'm not sure if there is even anything relevant in the circular bar plot code, I simply found it online as a frame of reference for the circular design. The final code will be very similar to the density plot, taking data in nearly the same way (current data is just dummy data, but same concept).

I've never worked with matplotlib and seaborn before, so not sure if what I'm going for is even possible. Also, I am aware that a circular density plot may not be the best or most practical choice to sharing data, but the circular design holds more importance in this case.

Todd Burus
  • 963
  • 1
  • 6
  • 20
Sharky
  • 67
  • 4

1 Answers1

3

In theory, you can set the projection of the axes to "polar" and then it will work:

x = np.random.vonmises(0, 2, 100)
f, ax = plt.subplots(subplot_kw=dict(projection='polar'))
sns.kdeplot(x)

But this won't truly be a circular density, because to compute that you would want to use a von mises kernel, not a gaussian that is wrapped to polar coordinates. Unfortunately, I think you'll need to compute the circular density yourself, and then plot it as a line.

mwaskom
  • 46,693
  • 16
  • 125
  • 127
  • For flavour see the comments on https://stats.stackexchange.com/q/608370/76901 - it's apparently not so crucial that von Mises be used, although if it were fully supported in Seaborn I'd certainly use it. – Reinderien Mar 05 '23 at 02:37
  • That answer doesn't seem to be about _kernel density estimation_ so I'm not sure how much it applies here. – mwaskom Mar 05 '23 at 18:02