如何用imshow在子图中按流派绘制Pandas多颜色列表
问题描述
我想可视化不同流派音乐发行作品的主色调,使用以下代码实现时出现问题:所有流派的颜色都被分配到第一行,没有按流派分组显示在对应的单独行中。
原代码
genres_of_interest = ['dutch drill', 'dutch pop', 'dutch hip hop'] # 创建筛选后的DataFrame filtered_df = df[df['Genre'].isin(genres_of_interest)] # 按流派分组,提取唯一主色调 grouped = filtered_df.groupby('Genre')['Main_Colors'].apply(lambda x: list(set([color for sublist in x for color in sublist]))) # 设置画布和坐标轴 fig, ax = plt.subplots(figsize=(12, len(genres_of_interest))) # 绘制每个流派的颜色矩阵 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) # 移除刻度标签 ax.set_xticks([]) ax.set_yticks([]) # 设置标题 plt.title('Colors by Genre') # 展示图像 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)]
修复方案
原代码问题在于每次调用imshow会覆盖之前的绘制内容,且未指定颜色条的y轴位置,导致所有颜色堆叠在第一行。以下是修复后的代码:
import numpy as np import matplotlib.pyplot as plt genres_of_interest = ['dutch drill', 'dutch pop', 'dutch hip hop'] # 创建筛选后的DataFrame filtered_df = df[df['Genre'].isin(genres_of_interest)] # 按流派分组,提取唯一主色调 grouped = filtered_df.groupby('Genre')['Main_Colors'].apply(lambda x: list(set([color for sublist in x for color in sublist]))) # 设置画布,根据流派数量调整高度 fig, ax = plt.subplots(figsize=(12, len(genres_of_interest)*1.2)) # 遍历每个流派绘制颜色条 for i, genre in enumerate(genres_of_interest): colors = grouped.get(genre, []) if not colors: continue # 将RGB整数转换为matplotlib要求的0-1浮点数 color_matrix = np.array(colors) / 255.0 # 指定颜色条的绘制范围,对应第i行 ax.imshow(color_matrix[np.newaxis, :], aspect='auto', extent=[0, len(colors), i-0.4, i+0.4]) # 添加流派名称到左侧 ax.text(-0.5, i, genre, va='center', ha='right', fontsize=10) # 配置坐标轴 ax.set_yticks(range(len(genres_of_interest))) ax.set_yticklabels([]) # 隐藏默认y轴标签 ax.set_ylim(-0.5, len(genres_of_interest)-0.5) # 确保所有行都显示 ax.set_xticks([]) # 隐藏x轴标签 # 设置标题 plt.title('各流派音乐作品主色调分布') plt.tight_layout() plt.show()
核心修改说明
- 颜色值归一化:matplotlib要求RGB值为0-1的浮点数,需将原数据中0-255的整数除以255转换
- 指定绘制范围:通过
extent参数控制每个颜色条的y轴区间,确保每个流派对应独立一行 - 画布适配:根据流派数量动态调整画布高度,避免内容拥挤
- 坐标轴范围校准:手动设置y轴范围,保证所有流派的行完整显示
内容的提问来源于stack exchange,提问作者jsb92
相关产品推荐
相关产品推荐

