0

I have this code:

import matplotlib.pyplot as plt
import pandas as pd
df = pd.DataFrame({
    'Name': ['A', 'B', 'C', 'D', 'E', 'F'],
    'Value': [10, 2, 23, 87, 12, 65]
})


circles = circlify.circlify(
    df['Value'].tolist(), 
    show_enclosure=False, 
    target_enclosure=circlify.Circle(x=0, y=0, r=1)
)

# Create just a figure and only one subplot
fig, ax = plt.subplots(figsize=(10,10))

# Title
ax.set_title('Basic circular packing')

# Remove axes
ax.axis('off')

# Find axis boundaries
lim = max(
    max(
        abs(circle.x) + circle.r,
        abs(circle.y) + circle.r,
    )
    for circle in circles
)
plt.xlim(-lim, lim)
plt.ylim(-lim, lim)

# list of labels
labels = df['Name']

# print circles
for circle, label in zip(circles, labels):
    x, y, r = circle
    ax.add_patch(plt.Circle((x, y), r, alpha=0.2, linewidth=2,color='#e6d4ff'))
    plt.annotate(
          label, 
          (x,y ) ,
          va='center',
          ha='center',
          size=12
     )

It produces this output:

enter image description here

I wanted to change the colour of just one of the circles (for example, the biggest circle).

I tried changing the colour from:

color='#e6d4ff'

to, for example, a list of colours:

color=['#e6d4ff','#e6d4ff','#e6d4ff','#e6d4ff','#e6d4ff','#ffc4c4']

with the error:

RGBA sequence should have length 3 or 4

I guess the error is saying if I'm providing a list, then the list should just be RGB dimensions.

Would someone be able to show me? (I couldn't see it in the python graph gallery e.g. [here][2] or the circlify doc here but maybe I've missed it?)

Slowat_Kela
  • 1,377
  • 2
  • 22
  • 60

1 Answers1

3

In each call to plt.Circle(...) you're only creating one circle, which has only one color. To assign different colors to different circles, the colors can be added into the for loop, e.g. : for circle, label, color in zip(circles, labels, colors):.

Note that circlify expects the list of values in sorted order, and that the returned list contains the circles sorted from smallest to largest. In your example code, D is the largest circle, but in your plot, you labeled it as F. Sorting the dataframe at the start and using that order helps to keep values and labels synchronized.

Here is the example code, having D as largest and with a different color (the code also changes a few plt. calls to ax. to be more consistent):

import matplotlib.pyplot as plt
import pandas as pd
import circlify

df = pd.DataFrame({'Name': ['A', 'B', 'C', 'D', 'E', 'F'],
                   'Value': [10, 2, 23, 87, 12, 65]})
df = df.sort_values('Value')  # the order is now ['B', 'A', 'E', 'C', 'F', 'D']
circles = circlify.circlify(df['Value'].tolist(),
                            show_enclosure=False,
                            target_enclosure=circlify.Circle(x=0, y=0, r=1))

fig, ax = plt.subplots(figsize=(10, 10))

ax.set_title('Basic circular packing')
ax.axis('off')
ax.set_aspect('equal')  # show circles as circles, not as ellipses

lim = max(max(abs(circle.x) + circle.r, abs(circle.y) + circle.r, )
          for circle in circles)
ax.set_xlim(-lim, lim)
ax.set_ylim(-lim, lim)

labels = df['Name']  # ['B', 'A', 'E', 'C', 'F', 'D']
colors = ['#ffc4c4' if val == df['Value'].max() else '#e6d4ff' for val in df['Value']]
for circle, label, color in zip(circles, labels, colors):
    x, y, r = circle
    ax.add_patch(plt.Circle((x, y), r, alpha=0.7, linewidth=2, color=color))
    ax.annotate(label, (x, y), va='center', ha='center', size=12)
plt.show()

circle packing with largest circle in different color

JohanC
  • 71,591
  • 8
  • 33
  • 66