Sam Comber
Sam Comber

Reputation: 1293

How to colour circular lines in polar chart (matplotlib)

I'm trying to to colour the circular line that corresponds to the value of 0 in a polar chart. This is what I want to achieve:

enter image description here

On this related question (Shading a segment between two lines on polar axis (matplotlib)), ax.fill_between is used to fill the space between two values, but I'm looking for a way to colour just the circular line where the value for each variable is 0.

If anybody has any tips that would be most appreciated! I've inserted a minimal working example below if anybody fancies having a go.

import matplotlib.pyplot as plt
import pandas as pd    

def make_spider(row, title, color):

    import math

    categories = list(df)
    N = len(categories)

    angles = [n / float(N) * 2 * math.pi for n in range(N)]
    angles += angles[:1]

    ax = plt.subplot(1, 5, row+1, polar=True)

    plt.xticks(angles[:-1], categories, color='grey', size=8)

    values = df.iloc[row].values.flatten().tolist()
    values += values[:1]

    ax.plot(angles, values, color=color, linewidth=2, linestyle='solid')
    ax.fill(angles, values, color=color, alpha = .4)

    plt.gca().set_rmax(.4)


my_dpi = 40

plt.figure(figsize=(1000/my_dpi, 1000/my_dpi), dpi=96)

my_palette = plt.cm.get_cmap('Set2', len(df.index)+1)


for row in range(0, len(df.index)):
     make_spider( row  = row, title='Cluster: ' + str(row), color=my_palette(row) )

Example dataframe here:

df = pd.DataFrame.from_dict({"no_rooms":{"0":-0.3470532925,"1":-0.082144001,"2":-0.082144001,"3":-0.3470532925,"4":-0.3470532925},"total_area":{"0":-0.1858487321,"1":-0.1685491141,"2":-0.1632483955,"3":-0.1769700284,"4":-0.0389887094},"car_park_spaces":{"0":-0.073703681,"1":-0.073703681,"2":-0.073703681,"3":-0.073703681,"4":-0.073703681},"house_price":{"0":-0.2416123064,"1":-0.2841806825,"2":-0.259622004,"3":-0.3529449824,"4":-0.3414842657},"pop_density":{"0":-0.1271390651,"1":-0.3105853643,"2":-0.2316607937,"3":-0.3297832328,"4":-0.4599021194},"business_rate":{"0":-0.1662745006,"1":-0.1426329043,"2":-0.1577528867,"3":-0.163560133,"4":-0.1099718326},"noqual_pc":{"0":-0.0251535462,"1":-0.1540641646,"2":-0.0204666924,"3":-0.0515740013,"4":-0.0445135996},"level4qual_pc":{"0":-0.0826103951,"1":-0.1777759951,"2":-0.114263357,"3":-0.1787044751,"4":-0.2709496389},"badhealth_pc":{"0":-0.105481688,"1":-0.1760349683,"2":-0.128215043,"3":-0.1560577648,"4":-0.1760349683}})

Upvotes: 2

Views: 2523

Answers (2)

louise
louise

Reputation: 1

There is an easier option:

fig_radar.add_trace(go.Scatterpolar(
        r = np.repeat(0, 360),
        dtheta = 360,
        mode = 'lines',
        name = 'cirlce',
        line_color = 'black',
        line_shape="spline"
    )

The addition of line_shape = "spline" makes it appear as a circle dtheta divides the coordinates in so many parts (at least I understood it this way and it works)

Upvotes: 0

Sheldore
Sheldore

Reputation: 39072

Probably a cheap hack based on the link you shared. The trick here is to simply use 360 degrees for fill_between and then use a very thin region around the circular line for 0 using margins such as -0.005 to 0.005. This way, you make sure the curve is centered around the 0 line. To make the line thicker/thinner you can increase/decrease this number. This can be straightforwardly extended to color all circular lines by putting it in a for loop.

ax.plot(angles, values, color=color, linewidth=2, linestyle='solid')
ax.fill(angles, values, color=color, alpha = .4)
ax.fill_between(np.linspace(0, 2*np.pi, 100), -0.005, 0.005, color='red', zorder=10) # <-- Added here

Other alternative could be to use a Circle patch as following

circle = plt.Circle((0, 0), 0.36, transform=ax.transData._b, fill=False, edgecolor='red', linewidth=2, zorder=10)
plt.gca().add_artist(circle)

but here I had to manually put 0.36 as the radius of the circle by playing around so as to put it exactly at the circular line for 0. If you know exactly the distance from the origin (center of the polar plot), you can put that number for exact position. At least for this case, 0.36 seems to be a good guess.

enter image description here

Upvotes: 3

Related Questions