Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Set Polygon Colors Matplotlib

I have a list of 10,000+ Matplotlib Polygon objects. Each polygon belongs to 1 of 20 groups. I want to differentiate which group a polygon belongs to by mapping each unique group to a unique color.

Here are some posts I've found with similar issues to mine:

Fill polygons with multiple colors in python matplotlib

How to fill polygons with colors based on a variable in Matplotlib?

How do I set color to Rectangle in Matplotlib?

These solutions simply apply a random color to each shape in the list. That is not what I am looking for. For me, each shape belonging to a particular group should have the same color. Any ideas?

Sample code:

from matplotlib.collections import PatchCollection
from matplotlib.patches import Polygon
from matplotlib import pyplot as plt

patches = []
colors = []
num_polys = 10000
for i in range(num_polys):
    patches.append(Polygon(poly_vertices[i], closed=True))
    colors.append(poly_colors[i])  # This line is pointless, but I'm letting you know that 
                                   # I have a particular color for each polygon

fig, ax = plt.subplots()
p = PatchCollection(patches, alpha=0.25)
ax.add_collection(p)
ax.autoscale()
plt.show()

Note that if you run this code, it won't work because poly_vertices and poly_colors haven't been defined. For now, just assume that poly_vertices is a list of polygon vertices, and poly_colors is a list of RGB colors and each list has 10000 entries.

For example: poly_vertices[0] = [(0, 0), (1, 0), (0, 1)], colors[0] = [1, 0, 0]

Thank you!

like image 226
Luke Stuemke Avatar asked Jun 23 '17 15:06

Luke Stuemke


2 Answers

Okay, I figured out what I was trying to do. I'll post the answer for anyone who may be having similar issues.

For some reason, setting the color in the polygon itself doesn't work. i.e.

Polygon(vertices, color=[1, 0, 0])

does not work.

Instead, after adding all the polygons to a collection, use

p = PatchCollection(patches)
p.set_color([1, 0, 0])

But I still want to group polygons by color. Therefore I need to add multiple PatchCollections -- one for each group type!

My original list of polygons were in no particular order, so the first polygon may belong to group 5, while its neighbor belongs to group 1, etc.

So, I first sorted the list by group number such that all polygons belonging to a particular group were right next to each other.

I then iterated through the sorted list and appended each polygon to a temporary list. Upon reaching a new group type, I knew it was time to add all the polygons in the temporary list to their own PatchCollection.

Here's some code for this logic:

a = [x for x in original_groups]                                  # The original group numbers (unsorted)
idx = sorted(range(len(a)), key=lambda k: a[k])                   # Get indices of sorted group numbers
current_group = original_groups[idx[0]]                           # Set the current group to the be the first sorted group number 
temp_patches = []                                                 # Create a temporary patch list

for i in idx:                                                     # iterate through the sorted indices
    if current_group == original_groups[i]:                       # Detect whether a  change in group number has occured
        temp_patches.append(original_patches[i])                  # Add patch to the temporary variable since group number didn't change
    else: 
        p = PatchCollection(temp_patches, alpha=0.6)              # Add all patches belonging to the current group number to a PatchCollection
        p.set_color([random.uniform(0, 1), random.uniform(0, 1), random.uniform(0, 1)])  # Set all shapes belonging to this group to the same random color
        ax.add_collection(p)                                      # Add all shapes belonging this group to the axes object
        current_group = original_groups[i]                        # The group number has changed, so update the current group number
        temp_patches = [original_patches[i]]                      # Reset temp_patches, to begin collecting patches of the next group number                                

p = PatchCollection(temp_patches, alpha=0.6)                      # temp_patches currently contains the patches belonging to the last group. Add them to a PatchCollection
p.set_color([random.uniform(0, 1), random.uniform(0, 1), random.uniform(0, 1)]) 
ax.add_collection(p)                         

ax.autoscale()                                                    # Default scale may not capture the appropriate region
plt.show()
like image 120
Luke Stuemke Avatar answered Sep 22 '22 07:09

Luke Stuemke


By turning on the match_original option, you can set the color of polygons individually (e.g. Polygon(vertices, color=[1, 0, 0]))

PatchCollection(patches, match_original=True)
like image 42
Miladiouss Avatar answered Sep 18 '22 07:09

Miladiouss