如何从字典中制作分组的小提琴图?

Eme*_*son 2 python dictionary matplotlib seaborn violin-plot

我想根据字典制作小提琴图。这是我的字典的示例,尽管我的实际字典有更多的患者和更多的值。

paired_patients={'Patient_1': {'n':[1, nan, 3, 4], 't': [5,6,7,8]},
                 'Patient_2': {'n':[9,10,11,12], 't':[14,nan,16,17]},
                 'Patient_3': {'n':[1.5,nan,3.5,4.5], 't':[5.5,6.5,7.5,8.5]}}
Run Code Online (Sandbox Code Playgroud)

对于每个患者,我希望有一组两个并排的小提琴图,一个'n'和一个用于't'. 我希望所有六个小提琴图都在同一个图上,共享 y 轴。

我正在尝试使用matplotlib violinplot,但我不确定如何在'dataset'选项中输入我的字典,也不知道如何按患者对'n'和进行分组't'

任何帮助将不胜感激!

Zep*_*hyr 5

回答

我建议将您的数据保存在pandas.DataFrame.
首先,我遍历患者以将数据保存在数据框中:

df = pd.DataFrame(columns = ['Patient', 'n', 't'])

for key, value in paired_patients.items():
    patient_df = pd.DataFrame({'Patient': [key]*len(value['n']),
                               'n': value['n'],
                               't': value['t']})
    df = df.append(patient_df, ignore_index = True)
Run Code Online (Sandbox Code Playgroud)

所以我得到:

      Patient     n    t
0   Patient_1   1.0    5
1   Patient_1   NaN    6
2   Patient_1   3.0    7
3   Patient_1   4.0    8
4   Patient_2   9.0   14
5   Patient_2  10.0  NaN
6   Patient_2  11.0   16
7   Patient_2  12.0   17
8   Patient_3   1.5  5.5
9   Patient_3   NaN  6.5
10  Patient_3   3.5  7.5
11  Patient_3   4.5  8.5
Run Code Online (Sandbox Code Playgroud)

然后我需要通过以下方式堆叠'n''t'pd.melt

df = pd.melt(frame = df,
             id_vars = 'Patient',
             value_vars = ['n', 't'],
             var_name = 'type',
             value_name = 'value')
Run Code Online (Sandbox Code Playgroud)

通过这种方式,数据框的形状如下:

      Patient type value
0   Patient_1    n     1
1   Patient_1    n   NaN
2   Patient_1    n     3
3   Patient_1    n     4
4   Patient_2    n     9
5   Patient_2    n    10
6   Patient_2    n    11
7   Patient_2    n    12
8   Patient_3    n   1.5
9   Patient_3    n   NaN
10  Patient_3    n   3.5
11  Patient_3    n   4.5
12  Patient_1    t     5
13  Patient_1    t     6
14  Patient_1    t     7
15  Patient_1    t     8
16  Patient_2    t    14
17  Patient_2    t   NaN
18  Patient_2    t    16
19  Patient_2    t    17
20  Patient_3    t   5.5
21  Patient_3    t   6.5
22  Patient_3    t   7.5
23  Patient_3    t   8.5
Run Code Online (Sandbox Code Playgroud)

最后,您可能需要将'value'列类型转换为float

df['value'] = df['value'].astype(float)
Run Code Online (Sandbox Code Playgroud)

现在可以使用以下方式绘制这些数据seaborn.violinplot

fig, ax = plt.subplots()

sns.violinplot(ax = ax,
               data = df,
               x = 'Patient',
               y = 'value',
               hue = 'type',
               split = True)

plt.show()
Run Code Online (Sandbox Code Playgroud)

全码

import matplotlib.pyplot as plt
import seaborn as sns
import pandas as pd
from math import nan

paired_patients = {'Patient_1': {'n': [1, nan, 3, 4], 't': [5, 6, 7, 8]},
                   'Patient_2': {'n': [9, 10, 11, 12], 't': [14, nan, 16, 17]},
                   'Patient_3': {'n': [1.5, nan, 3.5, 4.5], 't': [5.5, 6.5, 7.5, 8.5]}}

df = pd.DataFrame(columns = ['Patient', 'n', 't'])

for key, value in paired_patients.items():
    patient_df = pd.DataFrame({'Patient': [key]*len(value['n']),
                               'n': value['n'],
                               't': value['t']})
    df = df.append(patient_df, ignore_index = True)

df = pd.melt(frame = df,
             id_vars = 'Patient',
             value_vars = ['n', 't'],
             var_name = 'type',
             value_name = 'value')

df['value'] = df['value'].astype(float)

fig, ax = plt.subplots()

sns.violinplot(ax = ax,
               data = df,
               x = 'Patient',
               y = 'value',
               hue = 'type',
               split = True)

plt.show()
Run Code Online (Sandbox Code Playgroud)

阴谋

在此处输入图片说明


笔记

如果你有很多病人,你会沿着x轴有太多的数据,所以我建议你设置split = True以节省一些空间。
否则,如果你设置了split = False,你会得到:

在此处输入图片说明