2017-02-06 4 views
3

Есть ли у кого-нибудь идеи, как изменить масштаб оси X и тики, чтобы отобразить распределение процентилей, как показано на графике ниже? Это изображение от MATLAB, но я хочу использовать Python (через Matplotlib или Seaborn) для генерации.График распределения Percentile

Graph of distribution where there is lots of change >99%

От указателя по @paulh, я гораздо ближе. Этот код

import matplotlib 
matplotlib.use('Agg') 

import numpy as np 
import matplotlib.pyplot as plt 
import probscale 
import seaborn as sns 

clear_bkgd = {'axes.facecolor':'none', 'figure.facecolor':'none'} 
sns.set(style='ticks', context='notebook', palette="muted", rc=clear_bkgd) 

fig, ax = plt.subplots(figsize=(8, 4)) 

x = [30, 60, 80, 90, 95, 97, 98, 98.5, 98.9, 99.1, 99.2, 99.3, 99.4] 
y = np.arange(0, 12.1, 1) 

ax.set_xlim(40, 99.5) 
ax.set_xscale('prob') 

ax.plot(x, y) 
sns.despine(fig=fig) 

Формирует следующий участок (обратите внимание на перераспределены оси Х)

Graph with non-linear x-axis

Что я нахожу гораздо более полезным, чем стандартная шкала:

Graph with normal x-axis

Я связался с автором оригинального графика, и они дали мне несколько указателей. Это фактически график шкалы логарифма с измененной осью x и значениями [100-val], с ручной маркировкой тиков x-оси. В приведенном ниже коде воссоздается исходное изображение с теми же данными примера, что и другие графики.

import matplotlib 
matplotlib.use('Agg') 

import numpy as np 
import matplotlib.pyplot as plt 
import seaborn as sns 

clear_bkgd = {'axes.facecolor':'none', 'figure.facecolor':'none'} 
sns.set(style='ticks', context='notebook', palette="muted", rc=clear_bkgd) 

x = [30, 60, 80, 90, 95, 97, 98, 98.5, 98.9, 99.1, 99.2, 99.3, 99.4] 
y = np.arange(0, 12.1, 1) 

# Number of intervals to display. 
# Later calculations add 2 to this number to pad it to align with the reversed axis 
num_intervals = 3 
x_values = 1.0 - 1.0/10**np.arange(0,num_intervals+2) 

# Start with hard-coded lengths for 0,90,99 
# Rest of array generated to display correct number of decimal places as precision increases 
lengths = [1,2,2] + [int(v)+1 for v in list(np.arange(3,num_intervals+2))] 

# Build the label string by trimming on the calculated lengths and appending % 
labels = [str(100*v)[0:l] + "%" for v,l in zip(x_values, lengths)] 


fig, ax = plt.subplots(figsize=(8, 4)) 

ax.set_xscale('log') 
plt.gca().invert_xaxis() 
# Labels have to be reversed because axis is reversed 
ax.xaxis.set_ticklabels(labels[::-1]) 

ax.plot([100.0 - v for v in x], y) 

ax.grid(True, linewidth=0.5, zorder=5) 
ax.grid(True, which='minor', linewidth=0.5, linestyle=':') 

sns.despine(fig=fig) 

plt.savefig("test.png", dpi=300, format='png') 

Это результирующий график: Graph with "inverted log scale"

+3

Вы написали любой код или положить любые усилия в этом сами? Если да, напишите здесь. –

+0

Я никоим образом не понимаю, почему этот вопрос был закрыт как * слишком широкий *. Хотя в нем отсутствует хорошее описание проблемы, сама проблема становится очевидной из-за взгляда на график. Если бы был способ создать такой график, он бы, конечно, взял только пару строк кода, поэтому ответ не был бы слишком длинным и не ожидал, что там будет слишком много возможных ответов. – ImportanceOfBeingErnest

+0

@Chris Osterwood Пожалуйста, предоставьте команду matlab, которая производит этот вид графика, а также предоставит четкое описание проблемы в текстовой форме, а не только путем публикации изображения. Вы можете сделать это, разместив их как комментарий, чтобы более опытные пользователи могли включить их в вопрос. – ImportanceOfBeingErnest

ответ

1

Эти типы графиков популярны в низкой латентностью сообщества для построения распределения задержки. Когда речь идет о задержках, большая часть интересной информации, как правило, находится в более высоких процентилях, поэтому логарифмический вид имеет тенденцию работать лучше. Я впервые увидел эти графики, используемые в https://github.com/giltene/jHiccup и https://github.com/HdrHistogram/.

Приведенный график был сгенерирован следующий код

n = ceil(log10(length(values)));   
p = 1 - 1./10.^(0:0.01:n); 
percentiles = prctile(values, p * 100); 
semilogx(1./(1-p), percentiles); 

ось х была помечена с кодом ниже

labels = cell(n+1, 1); 
for i = 1:n+1 
    labels{i} = getPercentileLabel(i-1); 
end 
set(gca, 'XTick', 10.^(0:n)); 
set(gca, 'XTickLabel', labels); 

% {'0%' '90%' '99%' '99.9%' '99.99%' '99.999%' '99.999%' '99.9999%'} 
function label = getPercentileLabel(i) 
    switch(i) 
     case 0 
      label = '0%'; 
     case 1 
      label = '90%'; 
     case 2 
      label = '99%'; 
     otherwise 
      label = '99.'; 
      for k = 1:i-2 
       label = [label '9']; 
      end 
      label = [label '%']; 
    end 
end 
+0

Флориан - Спасибо за публикацию кода MATLAB, я уверен, что это будет полезно для кого-то еще в будущем. Я согласен с тем, что этот вид масштаба гораздо более понятен для данных с «высокими хвостами». –

Смежные вопросы