Amplifica los valores que son similares usando Numpy o Scipy en Python

Tengo una matriz numpy que se está graficando usando Matplotlib. Mi problema es que los valores son muy similares, por lo que cuando se grafica la legibilidad no existe.

0,0,0,0,0,0,0,0,46.29821447,49.49781571,49.83072758,50.89081787,98.49113721,98.5522082,99.29547499,99.91765345,99.93779431,99.95351796,99.98066963,99.99294867,100 

Observe cómo se agrupan algunos de los valores. Mi pregunta: ¿hay algún método para iterar sobre la matriz numpy y determinar esos clústeres unidos y luego aplicar una amplificación que los separe excluyendo los valores cero? Cuando los graficé en Matplotlib esta es la gráfica grafico

 x = np.array([1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21]) y = np.array([0,0,0,0,0,0,0,0,46.29821447,49.49781571,49.83072758,50.89081787,98.49113721,98.5522082,99.29547499,99.91765345,99.93779431,99.95351796,99.98066963,99.99294867,100]) my_xticks = ['<2.5 uS', '<5 uS', '<10 uS', '<20 uS', '<30 uS', '<40 uS', '<50 uS', '<60 uS', '<70 uS', '<80 uS', '<90 uS', '<100 uS', '<200 uS', '<250 uS', '<350 uS', '<500 uS', '<1 mS', '<2 uS', '<5 mS', '<10 mS', '<1 S'] my_yticks = [0,20,40,60,80,90,95,98,99,99.7,99.9,99.97,99.99,99.997,99.999,99.9997,99.9999,99.99999,99.999999] plt.xticks(x, my_xticks) plt.gca().axes.get_yaxis().set_ticks([0,20,40,60,80,90,95,98,99,99.7,99.9,99.97,99.99,99.997,99.999,99.9997,99.9999,99.99999,99.999999]) plt.yticks(y, my_yticks) plt.plot(x,y, '-r') plt.plot(x,y, '.') plt.ylim(bottom=-5, top=105) plt.grid(axis='y') plt.xlabel('Latency in Micro Milli Second') plt.ylabel('Probability in %') plt.title('Probability Distribution') plt.show() 

Arriba está mi código, supongo que lo que estoy buscando es un algoritmo de ordenamiento de cubetas, donde si ciertos valores son x cantidad cercana entre sí, aumentan sus valores por x cantidad, de modo que cuando graficé la matriz recién generada, los puntos en la gráfica que estaban realmente cerca uno del otro, ya que les añadimos x cantidad en la nueva matriz, ahora estamos separados y son más legibles.

ACTUALIZAR

He actualizado un poco mi código para obtener el mismo gráfico anterior con 15 gráficos diferentes que componen el mismo gráfico.

 x = np.array([1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21]) # Need to create a function that detects similar values to the first 2 digits 49.x 49.x 99.x 99.x and takes the min and max and assigns it to ylim dynamically y = np.array([0,0,0,0,0,0,0,0,46.29821447,49.49781571,49.83072758,50.89081787,98.49113721,98.5522082,99.29547499,99.91765345,99.93779431,99.95351796,99.98066963,99.99294867,100]) #override x ticks with latency labels my_xticks = ['<2.5 uS', '<5 uS', '<10 uS', '<20 uS', '<30 uS', '<40 uS', '<50 uS', '<60 uS', '<70 uS', '<80 uS', '<90 uS', '<100 uS', '<200 uS', '<250 uS', '<350 uS', '<500 uS', '<1 mS', '<2 uS', '<5 mS', '<10 mS', '<1 S'] f,(ax,ax2,ax3,ax4,ax5,ax6,ax7,ax8,ax9,ax10,ax11,ax12,ax13,ax14,ax15) = plt.subplots(15,1,sharex=True) #plot array to iterate over and assign different matplot properties for the graph plotArray = ax,ax2,ax3,ax4,ax5,ax6,ax7,ax8,ax9,ax10,ax11,ax12,ax13,ax14,ax15 #adjust the value formatter to read upto 7 decimal points 99.xxxxxxx majorFormatter = FormatStrFormatter('%.7f') #adjust the vertical spacing between each plot to 0 to stitch them together (no space) plt.subplots_adjust(hspace=0) #override x tick labels with custom latency labels plt.xticks(x, my_xticks) # start a for loop targeting the 15 different plots to assign properties. for var, i in enumerate(plotArray): #Y-axis grid lines i.grid(axis='y') #red line i.plot(x,y, '-r') #points for each value i.plot(x,y, '.') #over ride y tick labels to only show the tick labels of each data point i.set_yticks(y) #override value format on yaxis to read 7 decimal points i.yaxis.set_major_formatter(majorFormatter) #first plot if i is (plotArray[0]): i.spines['top'].set_visible(True) i.tick_params(axis='x', which='both', bottom='off', top='on', labelbottom='off') #last plot elif i is (plotArray[-1]): i.tick_params(axis='x', which='both', bottom='on', top='off', labelbottom='on') i.spines['bottom'].set_visible(True) i.spines['top'].set_visible(False) #inbetween plots else: i.spines['bottom'].set_visible(False) i.spines['top'].set_visible(False) i.tick_params(axis='x', which='both', bottom='off', top='off', labelbottom='off') # Values should be dynamiclly assigned due to different cluster values which are graphed on top of each other ax.set_ylim(99.95,100) ax2.set_ylim(99.8,99.95) ax3.set_ylim(99.5,99.8) ax4.set_ylim(99,99.5) ax5.set_ylim(98.5,99) ax6.set_ylim(98,98.5) ax7.set_ylim(90,98) ax8.set_ylim(86,90) ax9.set_ylim(70,86) ax10.set_ylim(60,70) ax11.set_ylim(50,60) ax12.set_ylim(45,50) ax13.set_ylim(40,45) ax14.set_ylim(30,40) ax15.set_ylim(0,30) plt.show() 

Necesito poder repasar la matriz que son mis porcentajes que variarán.

0,0,0,0,0,0,0,0,46.29821447,49.49781571,49.83072758,50.89081787,98.49113721,98.5522082,99.29547499,99.91765345,99.93779431,99.95351796,99.98066963,99.99294867,100

Con el fin de asignar limitaciones dinámicas del eje Y al gráfico para garantizar que los puntos de datos en mi matriz se muestren correctamente en cada gráfico.

  1. Ir sobre la matriz y obtener valores que están muy cerca, es decir, 49.x 49.x 98.x 98.x 99.x 99.x
  2. capture esos números y para cada conjunto calcule el valor más alto y más pequeño, es decir, si tengo 4 valores para un conjunto 99.9995 99.99 99.9994 99.993394, generará (99.99, 99.9995) para ese conjunto y luego puedo asignarlo a una limitación yaxis para uno de las plots de los 15 para capturar esos puntos y asegurarse de que estén dispersos en la gráfica y sean legibles.

Es prácticamente imposible trazar datos como este de tal manera que represente con precisión tanto las diferencias de escala fina entre los cuantiles como los saltos a gran escala. Puedes perder el tiempo con un eje y discontinuo, pero al final, cuando tienes que aplicar todo tipo de no linealidades para ajustar los datos a tus ejes, se vuelve muy difícil interpretar la gráfica.

¿Hay alguna razón muy importante por la que tenga que trazar la función de distribución acumulada , en lugar de la función de densidad de probabilidad ?

Así es como se ve realmente el PDF de sus datos en los ejes semi-log:

 import numpy as np from matplotlib import pyplot as plt x = np.array([2.5E-06, 5.0E-06, 1.0E-05, 2.0E-05, 3.0E-05, 4.0E-05, 5.0E-05, 6.0E-05, 7.0E-05, 8.0E-05, 9.0E-05, 1.0E-04, 2.0E-04, 2.5E-04, 3.5E-04, 5.0E-04, 1.0E-03, 2.0E-03, 5.0E-03, 1.0E-02, 1.0E+00]) y = np.array([ 0. , 0. , 0. , 0. , 0. , 0. , 0. , 0. , 46.29821447, 49.49781571, 49.83072758, 50.89081787, 98.49113721, 98.5522082 , 99.29547499, 99.91765345, 99.93779431, 99.95351796, 99.98066963, 99.99294867, 100.]) / 100. # we can get a rough estimate the PDF from the derivative of the CDF using # second-order central differences (it would be better to evaluate the PDF # directly if you can) dx = np.gradient(x) dy = np.gradient(y) fig, ax = plt.subplots(1, 1) ax.set_xscale('log') ax.fill_between(x, 0, (dy / dx), alpha=0.5) ax.set_ylabel('Probability density') ax.set_xlabel('S') 

introduzca la descripción de la imagen aquí

En mi opinión, el PDF da una intuición mucho más clara de lo que está pasando. Básicamente, tiene una alta densidad de probabilidad para valores cercanos a ~ 70uS, un pico más pequeño alrededor de ~ 100uS, y luego una probabilidad casi nula en cualquier otra parte.

Como puede ver, estos picos en el PDF son muy nítidos, lo que significa que cuando calcula el CDF (integral) termina con una gran cantidad de cuantiles que son muy similares, luego grandes saltos correspondientes a donde está la mayor parte de la densidad de probabilidad.

Los saltos en el CDF (correspondientes a los picos en el PDF) son probablemente las características más destacadas de la distribución de probabilidad, ya que reflejan los valores que es más probable que muestre.