X Tutup
Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
77 changes: 77 additions & 0 deletions examples/statistics/customized_violin_demo.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
# Customizing violin plots
#
#

import matplotlib.pyplot as plt
import numpy as np


# functions to calculate percentiles and adjacent values
def percentile(vals, p):
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why not use np.percentile?

N = len(vals)
n = p*(N+1)
k = int(n)
d = n-k
if k <= 0:
return vals[0]
if k >= N:
return vals[N-1]
return vals[k-1] + d*(vals[k] - vals[k-1])


def adjacent_values(vals):
q1 = percentile(vals, 0.25)
q3 = percentile(vals, 0.75)
uav = q3 + (q3-q1)*1.5
if uav > vals[-1]:
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can use np.clip here

uav = vals[-1]
if uav < q3:
uav = q3
lav = q1 - (q3-q1)*1.5
if lav < vals[0]:
lav = vals[0]
if lav > q1:
lav = q1
return [lav, uav]

# create test data
dat = [np.random.normal(0, std, 100) for std in range(6, 10)]
lab = ['a', 'b', 'c', 'd'] # labels
med = [] # medians
iqr = [] # inter-quantile ranges
avs = [] # upper and lower adjacent values
for arr in dat:
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Much of this could be wrapped up in a function with a siganture like def vln(ax, data, style)

sarr = sorted(arr)
med.append(percentile(sarr, 0.5))
iqr.append([percentile(sarr, 0.25), percentile(sarr, 0.75)])
avs.append(adjacent_values(sarr))

# plot the violins
fig, ax = plt.subplots(nrows=1, ncols=1, figsize=(7, 5))
parts = ax.violinplot(dat, showmeans=False, showmedians=False,
showextrema=False)

# plot medians and averages
for i in range(len(med)):
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can do the lines with a single call to ax.vlines and all of the markes with a single call to ax.plot. On the other hand, if it is the idea to be able to make a single violin invisible at a time this way might be better.

Can you collect the returned artists into a data structure of some sort (probably a dictionary per violin?)?

ax.plot([i+1, i+1], avs[i], '-', c='black', lw=1)
ax.plot([i+1, i+1], iqr[i], '-', c='black', lw=5)
ax.plot(i+1, med[i], 'o', mec='none', c='white', ms=6)

# customize colors
for pc in parts['bodies']:
pc.set_facecolor('#D43F3A')
pc.set_edgecolor('black')
pc.set_alpha(1)

ax.get_xaxis().set_tick_params(direction='out')
ax.xaxis.set_ticks_position('bottom')
ax.set_xticks([x+1 for x in range(len(lab))])
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

np.arange(1, len(lab) + 1)

ax.set_xticklabels(lab)
ax.set_xlim(0.25, len(lab)+0.75)
ax.set_ylabel('ylabel')
ax.set_xlabel('xlabel')
ax.set_title('customized violin plot')

plt.subplots_adjust(bottom=0.15)

plt.show()
X Tutup