Python 小提琴图(violinplot)

1. 两种不同shape的数据

这个问题也不是很理解, ax.violinplot() 需要一个 dataset , 如果我们要绘制多个小提琴, 那么 dataset 应该是一个二维数据

1.1 list类型

import numpy as np
import matplotlib.pyplot as plt
import time

positions=[1,2,4,7]
data=[
    np.random.normal(1,5,100).tolist(),
    np.random.normal(20,5,100).tolist(),
    np.random.normal(30,5,100).tolist(),
    np.random.normal(40,5,100).tolist(),
]

print(len(data))

fig,ax=plt.subplots()

ax.violinplot(data,positions,showmeans=True,showmedians=True)


import os

SaveDir = 'result/'
if not os.path.exists(SaveDir):
    os.makedirs(SaveDir)
now = time.strftime("%Y_%m%d_%H%M_%S", time.localtime(
    time.time()))  # 获得当前时间 2021_1108_2310_22
SaveFile = SaveDir + 'zzz' + '_' + now + '.png'  
plt.savefig(SaveFile)
print(SaveFile +    ' ==================>>> has been complete')
plt.close()

此时 data 的每一行构成一个 violin , 合乎我们的理解

listdataf1

1.2 numpy.ndarray 类型

这个时候如果 np 数组的 shape 是 4*100, 程序是报错的,此时 violinplot 是按照 列 来读取 data 的,就会构造100个violin,而 position 只指定了 4 个 位置。当然,不指定 position 也是可以的,不过画出来的图不是预期的了。

如果 ndarray 类型 的 dataset 的 shape 是 4*100,不指定 position 参数

import numpy as np
import matplotlib.pyplot as plt

positions = [1, 2, 4, 7]

data = np.zeros((4, 100))

data[0] = np.random.normal(1, 5, 100)
data[1] = np.random.normal(20, 5, 100)
data[2] = np.random.normal(30, 5, 100)
data[3] = np.random.normal(40, 5, 100)

fig, ax = plt.subplots()

ax.violinplot(data, showmeans=True, showmedians=True)

得到

errorviolin


只能将 ndarray 类型的 dataset 的 shape 改成 100*4

ndarray violin

import numpy as np
import matplotlib.pyplot as plt
import time

positions = [1, 2, 4, 7]

data = np.zeros((100, 4))

data[:,0]=np.random.normal(1,5,100)
data[:,1]=np.random.normal(20,5,100)
data[:,2]=np.random.normal(30,5,100)
data[:,3]=np.random.normal(40,5,100)

fig, ax = plt.subplots()

ax.violinplot(data,positions, showmeans=True, showmedians=True)

2.为小提琴图添加图例

ax.violinplot() 无法直接添加图例,可以使用带颜色的 patch 来描述对应的 violin

import matplotlib.pyplot as plt
import os
import time
import numpy as np

v1=np.random.normal(1,5,100)

v2=np.random.normal(20,5,100)

v3=np.random.normal(30,5,100) 

v4=np.random.normal(40,5,100) 

fig, ax = plt.subplots() #(figsize=(12,3.5))

h12=ax.violinplot([v1,v2],positions=[1,2],showmeans=True,showmedians=True)
h3=ax.violinplot(v3,positions=[4],showmeans=True,showmedians=True)
h4=ax.violinplot(v4,positions=[7],showmeans=True,showmedians=True)


h12_color=h12['bodies'][0].get_facecolor().flatten()
h3_color=h3['bodies'][0].get_facecolor().flatten()
h4_color=h4['bodies'][0].get_facecolor().flatten()


import matplotlib.patches as mpatches
h12_patch = mpatches.Patch(color=h12_color, label='violin1 and violin2')
h3_patch = mpatches.Patch(color=h3_color, label='violin3')
h4_patch = mpatches.Patch(color=h4_color, label='violin4')


ax.legend(handles=[h12_patch,h3_patch,h4_patch],loc=4)

一个 ax.violinplot() 如果同时绘制多个 [v1, v2], 就作为整体一起处理了。

violine with legend

首先获得 violin 的颜色,然后为每个 violin 添加一个patch

h12_color=h12['bodies'][0].get_facecolor().flatten()

import matplotlib.patches as mpatches
h12_patch = mpatches.Patch(color=h12_color, label='violin1 and violin2')

3. 参考链接

matplotlib-为小提琴图制作标签

legend guide

Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐