2014-11-30 3 views
5

जो मैं देख सकता हूं, boxplot() विधि इनपुट के रूप में कच्चे मूल्यों (संख्याओं) के अनुक्रम की अपेक्षा करता है, जिसके बाद यह बॉक्सप्लॉट को आकर्षित करने के लिए प्रतिशतों की गणना करता है।क्या मैटप्लॉटिब बॉक्सप्लॉट को मूल इनपुट के बजाय प्रतिशत मूल्यों को आकर्षित करना संभव है?

मैं एक तरीका चाहता हूं जिसके द्वारा मैं प्रतिशत में पास कर सकूं और संबंधित boxplot प्राप्त कर सकूं।

उदाहरण के लिए:

मान लें कि मैं कई मानक के चलने तथा प्रत्येक बेंचमार्क के लिए मैं सुप्तावस्था (चल बिन्दु मान) मापा जाता है। अब इसके अतिरिक्त, मैंने इन मानों के लिए प्रतिशत का प्रीकंप्यूटेड किया है।

इसलिए प्रत्येक बेंचमार्क के लिए, मेरे पास न्यूनतम और अधिकतम के साथ 25 वां, 50 वां, 75 वां प्रतिशत है।

अब इन आंकड़ों को देखते हुए, मैं बेंचमार्क के लिए बॉक्स प्लॉट आकर्षित करना चाहता हूं।

+1

Su झुकाव: क्या आप कृपया समस्या को संक्षेप में बना सकते हैं? यही है, 'विलंबता' कहने के बजाय कुछ अमूर्तता का उपयोग करें। 'मैंने कुछ वास्तविक मूल्यों को माप लिया है यानी फ्लोटिंग पॉइंट्स, और मैं प्रतिशत गणना करना चाहता हूं ...'। – polarise

उत्तर

10

केवल प्रतिशत मूल्यों और आउटलाइजर्स (यदि कोई हो) का उपयोग करके बॉक्स प्लॉट खींचने के लिए मैंने customized_box_plot फ़ंक्शन बनाया है जो मूल रूप से मूल बॉक्स प्लॉट (छोटे नमूना डेटा से उत्पन्न) में विशेषताओं को संशोधित करता है ताकि यह आपके अनुसार फिट हो सके प्रतिशत मूल्य

customized_box_plot समारोह

def customized_box_plot(percentiles, axes, redraw = True, *args, **kwargs): 
    """ 
    Generates a customized boxplot based on the given percentile values 
    """ 

    box_plot = axes.boxplot([[-9, -4, 2, 4, 9],]*n_box, *args, **kwargs) 
    # Creates len(percentiles) no of box plots 

    min_y, max_y = float('inf'), -float('inf') 

    for box_no, (q1_start, 
       q2_start, 
       q3_start, 
       q4_start, 
       q4_end, 
       fliers_xy) in enumerate(percentiles): 

     # Lower cap 
     box_plot['caps'][2*box_no].set_ydata([q1_start, q1_start]) 
     # xdata is determined by the width of the box plot 

     # Lower whiskers 
     box_plot['whiskers'][2*box_no].set_ydata([q1_start, q2_start]) 

     # Higher cap 
     box_plot['caps'][2*box_no + 1].set_ydata([q4_end, q4_end]) 

     # Higher whiskers 
     box_plot['whiskers'][2*box_no + 1].set_ydata([q4_start, q4_end]) 

     # Box 
     box_plot['boxes'][box_no].set_ydata([q2_start, 
              q2_start, 
              q4_start, 
              q4_start, 
              q2_start]) 

     # Median 
     box_plot['medians'][box_no].set_ydata([q3_start, q3_start]) 

     # Outliers 
     if fliers_xy is not None and len(fliers_xy[0]) != 0: 
      # If outliers exist 
      box_plot['fliers'][box_no].set(xdata = fliers_xy[0], 
              ydata = fliers_xy[1]) 

      min_y = min(q1_start, min_y, fliers_xy[1].min()) 
      max_y = max(q4_end, max_y, fliers_xy[1].max()) 

     else: 
      min_y = min(q1_start, min_y) 
      max_y = max(q4_end, max_y) 

     # The y axis is rescaled to fit the new box plot completely with 10% 
     # of the maximum value at both ends 
     axes.set_ylim([min_y*1.1, max_y*1.1]) 

    # If redraw is set to true, the canvas is updated. 
    if redraw: 
     ax.figure.canvas.draw() 

    return box_plot 

उपयोग

उलटा तर्क (अंत में कोड) का उपयोग करते हुए मैं इस example

>>> percentiles 
(-1.0597368367634488, 0.3977683984966961, 1.0298955252405229, 1.6693981537742526, 3.4951447843464449) 
(-0.90494930553559483, 0.36916539612108634, 1.0303658700697103, 1.6874542731392828, 3.4951447843464449) 
(0.13744105279440233, 1.3300645202649739, 2.6131540656339483, 4.8763411136047647, 9.5751914834437937) 
(0.22786243898199182, 1.4120860286080519, 2.637650402506837, 4.9067126578493259, 9.4660357513550899) 
(0.0064696168078617741, 0.30586770128093388, 0.70774153557312702, 1.5241965711101928, 3.3092932063051976) 
(0.007009744579241136, 0.28627373934008982, 0.66039691869500572, 1.4772725266672091, 3.221716765477217) 
(-2.2621660374110544, 5.1901313713883352, 7.7178532139979357, 11.277744848353247, 20.155971739152388) 
(-2.2621660374110544, 5.1884411864079532, 7.3357079047721054, 10.792299385806913, 18.842012119715388) 
(2.5417888074435702, 5.885996170695587, 7.7271286220368598, 8.9207423361593179, 10.846938621419374) 
(2.5971767318505856, 5.753551925927133, 7.6569980004033464, 8.8161056254143233, 10.846938621419374) 

नोट प्रतिशतक मान निकाला कि इस छोटे से रखने के लिए मैंने ओ नहीं दिखाया है utliers वैक्टर जो प्रत्येक प्रतिशत सरणी का 6 वां तत्व होगा।

भी ध्यान रखें कि सभी सामान्य अतिरिक्त kwargs/आर्ग के बाद से वे बस इसके अंदर boxplot विधि करने के लिए पारित कर रहे हैं इस्तेमाल किया जा सकता:

boxplot विधि

>>> fig, ax = plt.subplots() 
>>> b = customized_box_plot(percentiles, ax, redraw=True, notch=0, sym='+', vert=1, whis=1.5) 
>>> plt.show() 

Box Plot using Percentile values

व्याख्या व्यक्तिगत matplotlib.lines.Line2D उदाहरणों के लिए बॉक्सप्लॉट के घटकों को मैपिंग करने वाला एक शब्दकोश देता है बनाये गये।

matplotlib.pyplot.boxplot प्रलेखन से हवाला देते हुए:

शब्दकोश निम्नलिखित कुंजी (ऊर्ध्वाधर boxplots कल्पना करते हुए) है कि:

बक्से: चतुर्थकों और मंझला के विश्वास के अंतराल दिखा boxplot के मुख्य शरीर सक्षम करता है, तो ।

औसत: प्रत्येक बॉक्स के औसत पर क्षैतिज रेखाएं।

व्हिस्कर्स: सबसे चरम, एन-बाहरी डेटा बिंदुओं तक विस्तारित लंबवत रेखाएं। कैप्स: व्हिस्कर्स के सिरों पर क्षैतिज रेखाएं।

फ्लायर: डेटा का प्रतिनिधित्व करने वाले बिंदु जो व्हिस्कर्स (आउटलायर) से आगे बढ़ते हैं।

का अर्थ है: साधनों का प्रतिनिधित्व करने वाले बिंदु या रेखाएं।

उदाहरण के लिए निरीक्षण [-9, -4, 2, 4, 9]

>>> b = ax.boxplot([[-9, -4, 2, 4, 9],]) 
>>> b 
{'boxes': [<matplotlib.lines.Line2D at 0x7fe1f5b21350>], 
'caps': [<matplotlib.lines.Line2D at 0x7fe1f54d4e50>, 
<matplotlib.lines.Line2D at 0x7fe1f54d0e50>], 
'fliers': [<matplotlib.lines.Line2D at 0x7fe1f5b317d0>], 
'means': [], 
'medians': [<matplotlib.lines.Line2D at 0x7fe1f63549d0>], 
'whiskers': [<matplotlib.lines.Line2D at 0x7fe1f5b22e10>, 
      <matplotlib.lines.Line2D at 0x7fe20c54a510>]} 

>>> plt.show() 

A Sample box plot

के एक छोटे नमूना डेटा की boxplotmatplotlib.lines.Line2D वस्तुओं दो विधियों है कि मैं अपने समारोह में बड़े पैमाने पर उपयोग किया जाएगा है। set_xdata (या set_ydata) और get_xdata (या get_ydata)।

इन विधियों का उपयोग करके हम बेस बॉक्स प्लॉट की घटक पंक्तियों की स्थिति को अपने प्रतिशत मूल्यों के अनुरूप बदल सकते हैं (जो customized_box_plot फ़ंक्शन करता है)। घटक लाइनों की स्थिति में फेरबदल के बाद, आप कैनवास विभिन्न Line2D वस्तुओं के निर्देशांक के लिए प्रतिशतक से मैपिंग का सारांश figure.canvas.draw()

का उपयोग कर पुनः बनाने कर सकते हैं।

वाई निर्देशांक:

  • अधिकतम (q4_end - 4 चतुर्थक के अंत में) शीर्ष सबसे टोपी Line2D वस्तु से मेल खाती है।
  • न्यूनतम (q1_start - पहली तिमाही की शुरुआत) निम्नतम Line2D ऑब्जेक्ट की निम्नतम सीमा से मेल खाती है।
  • औसत मध्य (q3_start) औसत Line2D ऑब्जेक्ट से मेल खाता है।
  • 2 मूंछ बक्से के समाप्त होता है और चरम टोपियां के बीच झूठ (q1_start और q2_start - कम गलमुच्छा; q4_start और q4_end - ऊपरी गलमुच्छा)
  • बॉक्स वास्तव में एक दिलचस्प n आकार कम से कम एक टोपी से घिरा रेखा है हिस्से। n आकार की रेखा के चरम q2_start और q4_start से मेल खाते हैं।

एक्स निर्देशांक:

  • सेंट्रल x निर्देशांक (एकाधिक बॉक्स भूखंडों के लिए आम तौर पर कर रहे हैं 1, 2, 3 ...)
  • पुस्तकालय स्वचालित रूप से सीमांकन एक्स के आधार पर निर्देशांक की गणना करता है चौड़ाई निर्दिष्ट।

व्युत्क्रम समारोह boxplot dict से प्रतिशतक पुनः प्राप्त करने के:

def get_percentiles_from_box_plots(bp): 
    percentiles = [] 
    for i in range(len(bp['boxes'])): 
     percentiles.append((bp['caps'][2*i].get_ydata()[0], 
          bp['boxes'][i].get_ydata()[0], 
          bp['medians'][i].get_ydata()[0], 
          bp['boxes'][i].get_ydata()[2], 
          bp['caps'][2*i + 1].get_ydata()[0], 
          (bp['fliers'][i].get_xdata(), 
          bp['fliers'][i].get_ydata()))) 
    return percentiles 

नोट: कारण है कि मैं एक पूरी तरह से कस्टम boxplot विधि है, क्योंकि वहाँ कई इनबिल्ट द्वारा की पेशकश की विशेषताएं हैं नहीं किया बॉक्स प्लॉट जिसे पूरी तरह से पुन: उत्पन्न नहीं किया जा सकता है।

मुझे क्षमा करें अगर मैंने अनावश्यक रूप से कुछ ऐसा समझाया हो जो शायद स्पष्ट हो।

+0

यह एक अद्भुत जवाब है! बहुत आभारी। धन्यवाद –

+0

उत्कृष्ट जवाब। आपका बहुत बहुत धन्यवाद। – yoni

+0

इस के साथ तीन छोटी समस्याएं सामने आईं: (1) n_box परिभाषित नहीं किया गया है (यह आसान है ...) (2) यदि आप बिना फ्लायर के प्रतिशत प्रतिशत डेटा पास करना चाहते हैं, तो लूप विफल रहता है (box_no के लिए बेहतर लिखना, पीडीएटा अंक में (प्रतिशत) और उसके बाद pdata (3) नियमित रूप से विफल रहता है यदि आप पैच_आर्टिस्ट = ट्रू (कोई set_ydata विधि) – maschu

1

यहां इस उपयोगी दिनचर्या का एक अद्यतन संस्करण है। शिखर सेट करना सीधे भरे हुए बक्से (पैचआर्टिस्ट = ट्रू) और अपूर्ण दोनों के लिए काम करता है।

def customized_box_plot(percentiles, axes, redraw = True, *args, **kwargs): 
    """ 
    Generates a customized boxplot based on the given percentile values 
    """ 
    n_box = len(percentiles) 
    box_plot = axes.boxplot([[-9, -4, 2, 4, 9],]*n_box, *args, **kwargs) 
    # Creates len(percentiles) no of box plots 

    min_y, max_y = float('inf'), -float('inf') 

    for box_no, pdata in enumerate(percentiles): 
     if len(pdata) == 6: 
      (q1_start, q2_start, q3_start, q4_start, q4_end, fliers_xy) = pdata 
     elif len(pdata) == 5: 
      (q1_start, q2_start, q3_start, q4_start, q4_end) = pdata 
      fliers_xy = None 
     else: 
      raise ValueError("Percentile arrays for customized_box_plot must have either 5 or 6 values") 

     # Lower cap 
     box_plot['caps'][2*box_no].set_ydata([q1_start, q1_start]) 
     # xdata is determined by the width of the box plot 

     # Lower whiskers 
     box_plot['whiskers'][2*box_no].set_ydata([q1_start, q2_start]) 

     # Higher cap 
     box_plot['caps'][2*box_no + 1].set_ydata([q4_end, q4_end]) 

     # Higher whiskers 
     box_plot['whiskers'][2*box_no + 1].set_ydata([q4_start, q4_end]) 

     # Box 
     path = box_plot['boxes'][box_no].get_path() 
     path.vertices[0][1] = q2_start 
     path.vertices[1][1] = q2_start 
     path.vertices[2][1] = q4_start 
     path.vertices[3][1] = q4_start 
     path.vertices[4][1] = q2_start 

     # Median 
     box_plot['medians'][box_no].set_ydata([q3_start, q3_start]) 

     # Outliers 
     if fliers_xy is not None and len(fliers_xy[0]) != 0: 
      # If outliers exist 
      box_plot['fliers'][box_no].set(xdata = fliers_xy[0], 
              ydata = fliers_xy[1]) 

      min_y = min(q1_start, min_y, fliers_xy[1].min()) 
      max_y = max(q4_end, max_y, fliers_xy[1].max()) 

     else: 
      min_y = min(q1_start, min_y) 
      max_y = max(q4_end, max_y) 

     # The y axis is rescaled to fit the new box plot completely with 10% 
     # of the maximum value at both ends 
     axes.set_ylim([min_y*1.1, max_y*1.1]) 

    # If redraw is set to true, the canvas is updated. 
    if redraw: 
     ax.figure.canvas.draw() 

    return box_plot 
+0

का उपयोग करते हैं तो आपको असफल हो जाता है। यदि कोई सोचता है कि बॉक्सप्लॉट में लेबल कैसे असाइन करें [यह] (https://stackoverflow.com/a/43460149/4155911) उत्तर इसे अच्छी तरह से दिखाता है tl; dr 'ax.set_xticklabels (x_ticks_labels, rotation = 'vertical', fontsize = 18)' – Rotkiv

0

यहाँ एक नीचे-ऊपर दृष्टिकोण जहां box_plot matplotlib के vline, Rectangle का उपयोग कर का निर्माण है, और सामान्य plot कार्यों है

def boxplot(df, ax=None, box_width=0.2, whisker_size=20, mean_size=10, median_size = 10 , line_width=1.5, xoffset=0, 
        color=0): 
    """Plots a boxplot from existing percentiles. 

    Parameters 
    ---------- 
    df: pandas DataFrame 
    ax: pandas AxesSubplot 
     if to plot on en existing axes 
    box_width: float 
    whisker_size: float 
     size of the bar at the end of each whisker 
    mean_size: float 
     size of the mean symbol 
    color: int or rgb(list) 
     If int particular color of property cycler is taken. Example of rgb: [1,0,0] (red) 

    Returns 
    ------- 
    f, a, boxes, vlines, whisker_tips, mean, median 
    """ 

    if type(color) == int: 
     color = plt.rcParams['axes.prop_cycle'].by_key()['color'][color] 

    if ax: 
     a = ax 
     f = a.get_figure() 
    else: 
     f, a = plt.subplots() 

    boxes = [] 
    vlines = [] 
    xn = [] 
    for row in df.iterrows(): 
     x = row[0] + xoffset 
     xn.append(x) 

     # box 
     y = row[1][25] 
     height = row[1][75] - row[1][25] 
     box = plt.Rectangle((x - box_width/2, y), box_width, height) 
     a.add_patch(box) 
     boxes.append(box) 

     # whiskers 
     y = (row[1][95] + row[1][5])/2 
     vl = a.vlines(x, row[1][5], row[1][95]) 
     vlines.append(vl) 

    for b in boxes: 
     b.set_linewidth(line_width) 
     b.set_facecolor([1, 1, 1, 1]) 
     b.set_edgecolor(color) 
     b.set_zorder(2) 

    for vl in vlines: 
     vl.set_color(color) 
     vl.set_linewidth(line_width) 
     vl.set_zorder(1) 

    whisker_tips = [] 
    if whisker_size: 
     g, = a.plot(xn, df[5], ls='') 
     whisker_tips.append(g) 

     g, = a.plot(xn, df[95], ls='') 
     whisker_tips.append(g) 

    for wt in whisker_tips: 
     wt.set_markeredgewidth(line_width) 
     wt.set_color(color) 
     wt.set_markersize(whisker_size) 
     wt.set_marker('_') 

    mean = None 
    if mean_size: 
     g, = a.plot(xn, df['mean'], ls='') 
     g.set_marker('o') 
     g.set_markersize(mean_size) 
     g.set_zorder(20) 
     g.set_markerfacecolor('None') 
     g.set_markeredgewidth(line_width) 
     g.set_markeredgecolor(color) 
     mean = g 

    median = None 
    if median_size: 
     g, = a.plot(xn, df['median'], ls='') 
     g.set_marker('_') 
     g.set_markersize(median_size) 
     g.set_zorder(20) 
     g.set_markeredgewidth(line_width) 
     g.set_markeredgecolor(color) 
     median = g 

    a.set_ylim(np.nanmin(df), np.nanmax(df)) 
    return f, a, boxes, vlines, whisker_tips, mean, median 

यह है कि यह कैसे कार्रवाई में दिखाई देता है:

import numpy as np 
import pandas as pd 
import matplotlib.pylab as plt 

nopts = 12 
df = pd.DataFrame() 
df['mean'] = np.random.random(nopts) + 7 
df['median'] = np.random.random(nopts) + 7 
df[5] = np.random.random(nopts) + 4 
df[25] = np.random.random(nopts) + 6 
df[75] = np.random.random(nopts) + 8 
df[95] = np.random.random(nopts) + 10 
out = boxplot(df) 

enter image description here

संबंधित मुद्दे

 संबंधित मुद्दे