Home > OS >  I have a dataframe df and I want to draw a radial bar/column chart with the values mapped against th
I have a dataframe df and I want to draw a radial bar/column chart with the values mapped against th

Time:12-24

I have a dataframe df and I want to draw a radial bar/column chart with the values mapped against the cities.

The dataframe looks like:

City Counts
Leeds 5
Liverpool 7
Birmingham 8
Nottingham 14

I am able to get the horizontal bar chart but not the radial one

colors = ["red","green","blue","yellow","magenta","cyan"]
plt.barh("state", "counts", data = m, color = colors)
plt.xlabel("Number of Firearm Incidents per head")
plt.ylabel("LSOA Region")
plt.title("Firearm Incidents vs LSOA per head")
plt.show()

I want something like these two 1 2

CodePudding user response:

This is a possible approach:

# import pandas for data wrangling
import pandas as pd
import matplotlib.pyplot as plt
import numpy as np

# Build a dataset
df = pd.DataFrame({'City': ['Leeds', 'Liverpool', 'Birmingham', 'Nottingham'],
                   'Counts': [5, 7, 8, 14]})

# Reorder the dataframe
df = df.sort_values(by=['Counts'])

# initialize the figure
plt.figure(figsize=(20,10))
ax = plt.subplot(111, polar=True)
plt.axis('off')

# Constants = parameters controling the plot layout:
upperLimit = 100
lowerLimit = 30
labelPadding = 4

# Compute max and min in the dataset
max = df['Counts'].max()

# Let's compute heights: they are a conversion of each item value in those new coordinates
# In our example, 0 in the dataset will be converted to the lowerLimit (10)
# The maximum will be converted to the upperLimit (100)
slope = (max - lowerLimit) / max
heights = slope * df.Counts   lowerLimit

# Compute the width of each bar. In total we have 2*Pi = 360°
width = 2*np.pi / len(df.index)

# Compute the angle each bar is centered on:
indexes = list(range(1, len(df.index) 1))
angles = [element * width for element in indexes]
angles

# Draw bars
bars = ax.bar(
    x=angles, 
    height=heights, 
    width=width, 
    bottom=lowerLimit,
    linewidth=2, 
    edgecolor="white",
    color="#61a4b2",
)

# Add labels
for bar, angle, height, label in zip(bars,angles, heights, df["City"]):

    # Labels are rotated. Rotation must be specified in degrees :(
    rotation = np.rad2deg(angle)

    # Flip some labels upside down
    alignment = ""
    if angle >= np.pi/2 and angle < 3*np.pi/2:
        alignment = "right"
        rotation = rotation   180
    else: 
        alignment = "left"

    # Finally add the labels
    ax.text(
        x=angle, 
        y=lowerLimit   bar.get_height()   labelPadding, 
        s=label, 
        ha=alignment, 
        va='center', 
        rotation=rotation, 
        rotation_mode="anchor") 
  • Related