Это связано не с количеством переменных или размером графика, а с огромными различиями в распределении переменных. Я не могу получить доступ к вашим данным прямо сейчас, поэтому я проиллюстрирую их с помощью готового набора данных. Вы можете следовать за своим набором данных, выбирая три переменные с большей дисперсией и три с меньшей дисперсией. В качестве измерения дисперсии вы можете использовать дисперсию или даже диапазон данных (если у вас нет сумасшедших длинных хвостов) или что-то другое, я не уверен, что будет работать лучше.
rs = np.random.RandomState(42)
data = rs.randn(100, 6)
data[:, :3] *= 20
df = pd.DataFrame(data)
Посмотрите, что произойдет, если мы построим плотность с общими осями, чтобы они были прямо сопоставимы.
df.plot(kind='kde', subplots=True, layout=(3, 2), sharex=True, sharey=True)
plt.tight_layout()
Это более или менее то же самое, что вы можете увидеть на сюжете скрипки морского волка, но, конечно, транспонировано.
sns.violinplot(x='variable', y='value', data=pd.melt(df))
Это обычно отлично подходит для сравнения переменных, потому что вы можете рассматривать различия в ширине как различия в плотности. К сожалению, скрипка для переменных с большей дисперсией настолько узка, что вы не можете видеть ширину вообще, и вы теряете чувство формы. С другой стороны, переменные с меньшей дисперсией кажутся слишком короткими (на самом деле в вашем наборе данных некоторые из них являются просто горизонтальными линиями).
Для первой задачи вы можете заставить скрипки использовать все доступное горизонтальное пространство, используя scale='width'
, но тогда вы больше не сможете сравнивать плотность по переменным. На пиках ширина одинаковая, а плотность - нет.
sns.violinplot(x='variable', y='value', data=pd.melt(df), scale='width')
Кстати, это то, что по умолчанию делает скрипичный сюжет matplotlib.
plt.violinplot(df.T)
Что касается второй проблемы, я думаю, что ваш единственный вариант - нормализовать или стандартизировать переменные каким-либо образом.
sns.violinplot(x='variable', y='value', data=pd.melt((df - df.mean()) / df.std()))
Теперь у вас есть более четкое представление о каждой переменной в отдельности (сколько у них режимов, как они перекошены, какова длина хвостов ...), но вы не можете сравнивать ни масштаб, ни дисперсию по переменным.
Мораль этой истории в том, что вы не можете видеть все сразу, вы должны выбирать в зависимости от того, что вы ищете в данных.