Search code examples
pythonpandasmatplotlibgroup-byimshow

How to plot multiple color lists from pandas in subplots with imshow


I'm looking to visualize the colors of music releases per genre.

I'm using the below code. However, the issue is that it's not showing the colors grouped per genre on individual rows. It seems like it's assigning the colors across these genres to the first row instead of their corresponding genre, grouped per row.

The outcome looks like this;

enter image description here

genres_of_interest = ['dutch drill', 'dutch pop', 'dutch hip hop']

# Create a filtered DataFrame for the genres of interest
filtered_df = df[df['Genre'].isin(genres_of_interest)]

# Group the filtered DataFrame by 'Genre' and extract the unique colors from the 'Main_Colors' column
grouped = filtered_df.groupby('Genre')['Main_Colors'].apply(lambda x: list(set([color for sublist in x for color in sublist])))

# Set up the figure and axes
fig, ax = plt.subplots(figsize=(12, len(genres_of_interest)))

# Plot each genre's color matrix
for i, genre in enumerate(genres_of_interest):
    colors = grouped.get(genre, [])
    color_matrix = np.array(colors)
    ax.imshow([color_matrix], aspect='auto')
    ax.text(-0.05, i, genre, va='center', ha='right', fontsize=10)

# Remove the tick labels
ax.set_xticks([])
ax.set_yticks([])

# Set the plot title
plt.title('Colors by Genre')

# Show the plot
plt.show()
0        dutch pop  Jaap Reesema  spotify:album:3LCalQC4ZIayuqQSZuBAnJ   
1        dutch pop   Julia Zahra  spotify:album:6ZWgGdrkRDkhgXcXEQbSUZ   
2        dutch pop       Bertolf  spotify:album:1AVH0irCkKoElBzN8vhynT   
3        dutch pop    Glen Faria  spotify:album:6gdAvpnRN6VPdknvgSNyID   
4        dutch pop         Jengi  spotify:album:4nm8MRARxw1YRlVX8m2BBW   
..             ...           ...                                   ...   
136  dutch hip hop         Steen  spotify:album:2fAHea1XRZWhU25O4WZKAU   
137  dutch hip hop          Ajay  spotify:album:6Rp0g7eWIDSIxIpxP8B8l0   
138  dutch hip hop       Kingsta  spotify:album:7xdm2GmPdAjbq9gpRgcalC   
139  dutch hip hop     Mick Spek  spotify:album:5HG7pw6Nnxm91hpZ7dLefK   
140  dutch hip hop        Jerrih  spotify:album:16uxfTXWcaTpL9fz5uDzHt   

                                            Genre_Link    Friday  \
0    ?genre=dutch%20pop®ion=NL&date=20230414&hidedu...  20230414   
1    ?genre=dutch%20pop®ion=NL&date=20230414&hidedu...  20230414   
2    ?genre=dutch%20pop®ion=NL&date=20230414&hidedu...  20230414   
3    ?genre=dutch%20pop®ion=NL&date=20230414&hidedu...  20230414   
4    ?genre=dutch%20pop®ion=NL&date=20230414&hidedu...  20230414   
..                                                 ...       ...   
136  ?genre=dutch%20hip%20hop®ion=NL&date=20230421&...  20230421   
137  ?genre=dutch%20hip%20hop®ion=NL&date=20230421&...  20230421   
138  ?genre=dutch%20hip%20hop®ion=NL&date=20230421&...  20230421   
139  ?genre=dutch%20hip%20hop®ion=NL&date=20230421&...  20230421   
140  ?genre=dutch%20hip%20hop®ion=NL&date=20230421&...  20230421   

     numberoftracks                                    Album_Image_URL  \
0                 1  http://i.scdn.co/image/ab67616d00001e0255ce734...   
1                 1  http://i.scdn.co/image/ab67616d00001e020a3c941...   
2                 1  http://i.scdn.co/image/ab67616d00001e02396be8a...   
3                 1  http://i.scdn.co/image/ab67616d00001e02747d4bb...   
4                 4  http://i.scdn.co/image/ab67616d00001e02b000906...   
..              ...                                                ...   
136               7  http://i.scdn.co/image/ab67616d00001e02a3b237d...   
137               1  http://i.scdn.co/image/ab67616d00001e02d240f30...   
138              15  http://i.scdn.co/image/ab67616d00001e023b4acb2...   
139               1  http://i.scdn.co/image/ab67616d00001e02194c537...   
140               1  http://i.scdn.co/image/ab67616d00001e02cf59a38...   

    genre_rank country_rank                artist_ID releases_per_genre  \
0           70         6186  A5WxnXxSCyhDSyi6elhBZd4                 15   
1          137        60237  A57QuHq7IzyUgZsgl0g5fMI                 15   
2          141       119412  A6cs3EabebGIu559XRIpQty                 15   
3          169        52578  A0O0Hr8JCTPqXyPLdN6kzdC                 15   
4          213         3504  A4lgrPvofm0IT605L9OrOTN                 15   
..         ...          ...                      ...                ...   
136        265        25864  A4sf0XtUsKwVtg6YK72Dx2C                 45   
137        268       139247  A6blOShkI4PDC0gqCk6PQoa                 45   
138        313       483137  A3n6Lxlc9bF0mQWss8U1Yx5                 45   
139        314       146827  A23mbvDIZJjSK4y4KhwlnHi                 45   
140        333       119043  A0eKtd8T6YEkhuD9He27Jns                 45   

          Date                                        Main_Colors  
0   2023-04-14            [(52, 1, 0), (68, 2, 15), (153, 5, 66)]  
1   2023-04-14     [(41, 102, 54), (94, 79, 70), (233, 229, 223)]  
2   2023-04-14          [(12, 10, 9), (39, 34, 35), (92, 88, 90)]  
3   2023-04-14  [(140, 98, 50), (235, 215, 196), (178, 159, 138)]  
4   2023-04-14     [(33, 119, 78), (113, 33, 102), (101, 61, 96)]  
..         ...                                                ...  
136 2023-04-21        [(13, 44, 14), (49, 122, 51), (30, 92, 20)]  
137 2023-04-21     [(181, 155, 140), (116, 91, 76), (69, 73, 82)]  
138 2023-04-21        [(51, 29, 13), (11, 20, 14), (146, 75, 37)]  
139 2023-04-21      [(62, 34, 23), (155, 79, 35), (208, 143, 82)]  
140 2023-04-21   [(239, 214, 195), (210, 163, 96), (146, 85, 53)]

Solution

  • The number of color groups must be the same for each genre, in this case there are 5.

    Tested in python 3.11.2, pandas 2.0.1, matplotlib 3.7.1

    import pandas as pd
    import matplotlib.pyplot as plt
    
    # dutch pop and dutch hip hop have the same number of color arrays
    data = {'Genre': ['dutch pop', 'dutch pop', 'dutch pop', 'dutch pop', 'dutch pop',
                      'dutch hip hop', 'dutch hip hop', 'dutch hip hop', 'dutch hip hop', 'dutch hip hop'],
            'Main_Colors': [[(52, 1, 0), (68, 2, 15), (153, 5, 66)],
                            [(41, 102, 54), (94, 79, 70), (233, 229, 223)],
                            [(12, 10, 9), (39, 34, 35), (92, 88, 90)],
                            [(140, 98, 50), (235, 215, 196), (178, 159, 138)],
                            [(33, 119, 78), (113, 33, 102), (101, 61, 96)],
                            [(13, 44, 14), (49, 122, 51), (30, 92, 20)],
                            [(181, 155, 140), (116, 91, 76), (69, 73, 82)],
                            [(51, 29, 13), (11, 20, 14), (146, 75, 37)],
                            [(62, 34, 23), (155, 79, 35), (208, 143, 82)],
                            [(239, 214, 195), (210, 163, 96), (146, 85, 53)]]}
    df = pd.DataFrame(data)
    
    # combine all the lists of tuples, use set to make sure the tuples are unique, and needs to be a list (not a set) to plot
    groups = df.groupby('Genre')['Main_Colors'].sum().apply(set).apply(list)
    
    fig, ax = plt.subplots(figsize=(12, len(groups)))
    
    # plot all the data at once
    ax.imshow(groups.tolist())
    
    # add the labels
    ax.set_yticks(range(len(groups)), groups.index.tolist())
    plt.show()
    

    enter image description here

    • If the number of color groups do not match, they will have to be plotted separately, instead of as a single array.
      • The end of the shorter array will be empty (white).
    import pandas as pd
    import matplotlib.pyplot as plt
    
    # dutch pop has an extra color array compared to dutch hip hop
    data = {'Genre': ['dutch pop', 'dutch pop', 'dutch pop', 'dutch pop', 'dutch pop', 'dutch pop',
                      'dutch hip hop', 'dutch hip hop', 'dutch hip hop', 'dutch hip hop', 'dutch hip hop'],
            'Main_Colors': [[(52, 1, 0), (68, 2, 15), (153, 5, 66)],
                            [(52, 1, 200), (90, 10, 115), (153, 45, 166)],
                            [(41, 102, 54), (94, 79, 70), (233, 229, 223)],
                            [(12, 10, 9), (39, 34, 35), (92, 88, 90)],
                            [(140, 98, 50), (235, 215, 196), (178, 159, 138)],
                            [(33, 119, 78), (113, 33, 102), (101, 61, 96)],
                            [(13, 44, 14), (49, 122, 51), (30, 92, 20)],
                            [(181, 155, 140), (116, 91, 76), (69, 73, 82)],
                            [(51, 29, 13), (11, 20, 14), (146, 75, 37)],
                            [(62, 34, 23), (155, 79, 35), (208, 143, 82)],
                            [(239, 214, 195), (210, 163, 96), (146, 85, 53)]]}
    df = pd.DataFrame(data)
    
    # combine all the lists of tuples, use set to make sure the tuples are unique, and needs to be a list (not a set) to plot
    groups = df.groupby('Genre')['Main_Colors'].sum().apply(set).apply(list)
    
    fig, axes = plt.subplots(nrows=len(groups), ncols=1, figsize=(10, 1), sharex=True, gridspec_kw={'hspace': 0})
    
    for group, label, ax in zip(groups, groups.index, axes):
        ax.imshow([group])
        ax.set_yticks([0], [label])
    

    enter image description here