用Python绘制小提琴图主要用到violinplot这个函数,函数的API是
sns.violinplot(x=None, y=None, hue=None, data=None, order=None, hue_order=None, bw='scott', cut=2, scale='area', scale_hue=True, gridsize=100, width=0.8, inner='box', split=False, dodge=True, orient=None, linewidth=None, color=None, palette=None, saturation=0.75, ax=None, **kwargs)
参数:
x 和 y:分别指定数据的 x 轴和 y 轴。x 通常用于指定类别或分组数据,y 通常用于指定数值数据。
data:一个 DataFrame,用于指定数据集,可以在其中指定 x 和 y 列名,而不必显式传递 x 和 y。
hue:一个列名或变量,用于根据其值对数据进行分组,生成不同颜色的小提琴。
order 和 hue_order:指定 x 轴或 hue 中类别的显示顺序。
bw:控制小提琴图的带宽(它影响小提琴的平滑度,值越小越平滑,越大越粗糙)。
scale:控制小提琴图的宽度。可以设置为 "area"(面积相等,默认值)、"count"(按照样本数量标准化)、"width"(固定宽度)。
inner:设置小提琴内部图形的类型,可以是 "box"、"quart"、"point"、"stick" 或 None。默认为 "box"。
split:当使用 hue 参数进行分组时,设置为 True 时,将小提琴图拆分成两半,分别表示不同的 hue 类别。
palette:指定颜色调色板,用于不同类别的颜色着色。
showmedians:设置为 True 时,显示小提琴中位数的点。
showextrema:设置为 True 时,显示小提琴顶端和底端的线段。
showcaps:设置为 True 时,显示小提琴图的顶部和底部的线段。
inner_kwargs:一个字典,用于传递给内部图形绘制函数的其他参数。
代码:
import pandas as pd
import seaborn as sns
import matplotlib.pyplot as plt
# 创建一个示例DataFrame
data = {
"Category": ["A", "B", "A", "C", "B", "A", "C", "A", "B", "C"],
"Value": [5.1, 4.9, 5.5, 6.2, 5.7, 4.8, 6.5, 5.3, 6.0, 6.4]
}
df = pd.DataFrame(data)
# 绘制小提琴图
sns.violinplot(x=df["Category"], y=df["Value"])
# 显示图形
plt.show()
代码:
import seaborn as sns
import matplotlib.pyplot as plt
import pandas as pd
# 设置绘图风格和背景
sns.set(style="darkgrid")
# 创建一个示例DataFrame
data = {
"sepal_length": [5.1, 5.9, 6.9, 4.6, 6.0, 6.1, 5.6, 5.4, 6.2, 4.8],
}
df = pd.DataFrame(data)
# Make boxplot for one group only
sns.violinplot(y=df["sepal_length"])
plt.show()
代码
import pandas as pd
import seaborn as sns
import matplotlib.pyplot as plt
sns.set(style="darkgrid")
# 创建一个示例DataFrame
data = {
"Category": ["A", "B", "A", "C", "B", "A", "C", "A", "B", "C"],
"Value": [5.1, 4.9, 5.5, 6.2, 5.7, 4.8, 6.5, 5.3, 6.0, 6.4]
}
df = pd.DataFrame(data)
sns.violinplot(y=df["Category"], x=df["Value"])
plt.show()
代码:
import numpy as np
import matplotlib.pyplot as plt
import scipy.stats as st
import pandas as pd
# 加载您的CSV文件
your_data = pd.read_csv('violin_data.csv') # 替换 'violin_data.csv' 为您的数据文件路径
# 获取类别名称
classes = sorted(your_data["classes"].unique()) # 将代码中的"classes"更改为您的列名 "classes"
# 准备数据
y_data = [your_data[your_data["classes"] == c]["values"].values for c in classes] # 更改列名
jitter = 0.04
x_data = [np.array([i] * len(d)) for i, d in enumerate(y_data)]
x_jittered = [x + st.t(df=6, scale=jitter).rvs(len(x)) for x in x_data]
# 设置颜色
BG_WHITE = "#fbf9f4"
GREY_LIGHT = "#b4aea9"
GREY50 = "#7F7F7F"
BLUE_DARK = "#1B2838"
BLUE = "#2a475e"
BLACK = "#282724"
GREY_DARK = "#747473"
RED_DARK = "#850e00"
COLOR_SCALE = ["#1B9E77", "#D95F02", "#7570B3"]
POSITIONS = [0, 1, 2]
HLINES = [40, 50, 60]
# 创建图形和坐标轴对象
fig, ax = plt.subplots(figsize=(14, 10))
# 设置布局 ----------------------------------------------
# 背景颜色
fig.patch.set_facecolor(BG_WHITE)
ax.set_facecolor(BG_WHITE)
# 用于作为比例参考的水平线
for h in HLINES:
ax.axhline(h, color=GREY50, ls=(0, (5, 5)), alpha=0.8, zorder=0)
# 添加小提琴图 ----------------------------------------------------
# bw_method="silverman" 表示核密度估计的带宽使用Silverman法则计算
# 输出存储在 'violins' 中,用于自定义它们的外观
violins = ax.violinplot(
y_data,
positions=POSITIONS,
widths=0.45,
bw_method="silverman",
showmeans=False,
showmedians=False,
showextrema=False
)
# 自定义小提琴图 (移除填充,自定义线条等)
for pc in violins["bodies"]:
pc.set_facecolor("none")
pc.set_edgecolor(BLACK)
pc.set_linewidth(1.4)
pc.set_alpha(1)
# 添加箱线图 ---------------------------------------------------
# 注意,关于中位数和箱子的属性以字典形式传递。
medianprops = dict(
linewidth=4,
color=GREY_DARK,
solid_capstyle="butt"
)
boxprops = dict(
linewidth=2,
color=GREY_DARK
)
ax.boxplot(
y_data,
positions=POSITIONS,
showfliers=False, # 不显示超出箱顶和箱底的异常值
showcaps=False, # 不显示箱顶和箱底
medianprops=medianprops,
whiskerprops=boxprops,
boxprops=boxprops
)
# 添加 jittered 点 ----------------------------------------------
for x, y, color in zip(x_jittered, y_data, COLOR_SCALE):
ax.scatter(x, y, s=100, color=color, alpha=0.4)
# 添加均值标签 ------------------------------------------
means = [y.mean() for y in y_data]
for i, mean in enumerate(means):
# 添加表示均值的点
ax.scatter(i, mean, s=250, color=RED_DARK, zorder=3)
# 添加连接均值和标签的线
ax.plot([i, i + 0.25], [mean, mean], ls="dashdot", color="black", zorder=3)
# 添加均值标签
ax.text(
i + 0.25,
mean,
r"$\hat{\mu}_{\rm{mean}} = $" + str(round(mean, 2)),
fontsize=13,
va="center",
bbox=dict(
facecolor="white",
edgecolor="black",
boxstyle="round",
pad=0.15
),
zorder=10 # 确保线在顶部
)
# 自定义布局 -----------------------------------------------
# 隐藏轴线
ax.spines["right"].set_color("none")
ax.spines["top"].set_color("none")
# 自定义轴线颜色
ax.spines["left"].set_color(GREY_LIGHT)
ax.spines["left"].set_linewidth(2)
ax.spines["bottom"].set_color(GREY_LIGHT)
ax.spines["bottom"].set_linewidth(2)
# 自定义标签和刻度
ax.tick_params(length=0)
ax.set_yticks(HLINES)
ax.set_yticklabels(HLINES, size=15)
ax.set_ylabel("data", size=18, weight="bold")
# x轴标签包括每个物种的样本大小
xlabels = [f"{classes}\n(n={y_data[i].size})" for i, classes in enumerate(classes)]
ax.set_xticks(POSITIONS)
ax.set_xticklabels(xlabels, size=15, ha="center", ma="center")
ax.set_xlabel("class", size=18, weight="bold")
# 标题
fig.suptitle(
"Title",
x = 0.5,
y = 0.975,
ha="center",
fontsize=26,
fontname="Lobster Two",
color=BLUE,
weight="bold",
)
# 显示图形
plt.show()