文章目录
- 1. 前言
- 2. 实现
- 2.1 构建数据对
- 2.2 构建colors_map
- 2.3 绘制图
- 3. 完整示例
1. 前言
在散点图中,我们有时候希望把不同类别的点用不同颜色区分,并且不同类别有图例标签标明,实现类似如下的结果:
2. 实现
2.1 构建数据对
首先构建好 label -> (x, y)
的映射数据 Map,这一步是根据你的实际情况提前构建的,一般数据都是动态的,最终构建的数据格式:
label_to_xy = {
"label_A": [[1, 2, 3, 4, 5, 5, 3, 2], [2, 1, 3, 5, 4, 3, 4, 3]],
"label_B": [[10, 11, 12, 13, 14, 13, 12, 11], [15, 16, 13, 10, 14, 15, 13, 12]],
"label_C": [[8, 7, 8, 7, 8, 9], [10, 8, 9, 9, 10, 8]]
}
其中,列表中第一个是 x 轴坐标列表,第二个是 y 轴坐标列表。
2.2 构建colors_map
紧接着,根据构建好的数据,动态构建 colors_map
,用于绘制不同颜色的点:
import math
import random
import matplotlib.pyplot as plt
all_colors, colors_map = [], {}
for label in label_to_xy.keys():
color = generate_random_color(min_distance=0.3, previous_colors=all_colors)
all_colors.append(color)
colors_map[label] = color
def generate_random_color(min_distance=0.2, previous_colors=None, max_attempts=100):
"""
生成一个带有足够颜色通道差异的随机RGB颜色,确保与之前生成的颜色不相邻
"""
def color_distance(color1, color2):
"""计算两个颜色之间的欧氏距离"""
return math.sqrt(sum((c1 - c2) ** 2 for c1, c2 in zip(color1, color2)))
if previous_colors is None:
previous_colors = []
if not previous_colors:
return (random.random(), random.random(), random.random())
while True:
r = random.random()
g = random.random()
b = random.random()
min_distance_to_previous = min(color_distance(new_color, prev_color) for new_color in ((r, g, b),) for prev_color in previous_colors)
if min_distance_to_previous >= min_distance:
return (r, g, b)
2.3 绘制图
import math
import random
import matplotlib.pyplot as plt
plt.figure()
for l, xy in label_to_xy.items():
plt.scatter(xy[0], xy[1], label=l, c=[colors_map[l]])
plt.legend()
plt.show()
3. 完整示例
import math
import random
import matplotlib.pyplot as plt
def draw_pic(label_to_xy):
all_colors, colors_map = [], {}
for label in label_to_xy.keys():
color = generate_random_color(min_distance=0.3, previous_colors=all_colors)
all_colors.append(color)
colors_map[label] = color
plt.figure()
for l, xy in label_to_xy.items():
plt.scatter(xy[0], xy[1], label=l, c=[colors_map[l]])
plt.legend()
plt.show()
def generate_random_color(min_distance=0.2, previous_colors=None, max_attempts=100):
"""
生成一个带有足够颜色通道差异的随机RGB颜色,确保与之前生成的颜色不相邻
"""
def color_distance(color1, color2):
"""计算两个颜色之间的欧氏距离"""
return math.sqrt(sum((c1 - c2) ** 2 for c1, c2 in zip(color1, color2)))
if previous_colors is None:
previous_colors = []
if not previous_colors:
return (random.random(), random.random(), random.random())
while True:
r = random.random()
g = random.random()
b = random.random()
min_distance_to_previous = min(color_distance(new_color, prev_color) for new_color in ((r, g, b),) for prev_color in previous_colors)
if min_distance_to_previous >= min_distance:
return (r, g, b)
if __name__ == "__main__":
label_to_xy = {
"label_A": [[1, 2, 3, 4, 5, 5, 3, 2], [2, 1, 3, 5, 4, 3, 4, 3]],
"label_B": [[10, 11, 12, 13, 14, 13, 12, 11], [15, 16, 13, 10, 14, 15, 13, 12]],
"label_C": [[8, 7, 8, 7, 8, 9], [10, 8, 9, 9, 10, 8]]
}
draw_pic(label_to_xy)
欢迎关注本人,我是喜欢搞事的程序猿;一起进步,一起学习;
欢迎关注知乎/CSDN:SmallerFL
也欢迎关注我的wx公众号(精选高质量文章):一个比特定乾坤