2015-05-08 6 views
8

pandas cut() documentation बताता है कि: "सीमा शुल्क से बाहर परिणामस्वरूप स्पष्ट वस्तु में NA होगा।" यह मुश्किल बनाता है जब ऊपरी सीमा अनिवार्य रूप से स्पष्ट या महत्वपूर्ण नहीं है। उदाहरण के लिए:अनंत ऊपरी/निचले सीमाओं के साथ पांडा काट

cut (weight, bins=[10,50,100,200]) 

डिब्बे का उत्पादन होगा:

[(10, 50] < (50, 100] < (100, 200]] 

तो cut (250, bins=[10,50,100,200]) एक NaN का उत्पादन करेगा, के रूप में होगा cut (5, bins=[10,50,100,200])। मैं जो करने की कोशिश कर रहा हूं वह पहले उदाहरण के लिए > 200 और दूसरी के लिए < 10 का उत्पादन करता है।

मुझे पता है मैं cut (weight, bins=[float("inf"),10,50,100,200,float("inf")]) या समकक्ष कर सकता है, लेकिन रिपोर्ट शैली मैं अनुसरण कर रहा हूं (200, inf] तरह बातें की अनुमति नहीं है। मुझे भी एहसास है कि मैं वास्तव में cut() पर labels पैरामीटर के माध्यम से कस्टम लेबल निर्दिष्ट कर सकता हूं, लेकिन इसका मतलब है कि हर बार जब मैं bins समायोजित करता हूं, तो उन्हें समायोजित करना याद रखना, जो अक्सर हो सकता है।

क्या मैंने सभी संभावनाओं को समाप्त कर दिया है, या cut() में कहीं और pandas में कहीं और है जो मुझे ऐसा करने में मदद करेगा? मैं cut() के लिए एक रैपर फ़ंक्शन लिखने के बारे में सोच रहा हूं जो डिब्बे से वांछित प्रारूप में लेबल स्वचालित रूप से उत्पन्न करेगा, लेकिन मैं पहले यहां जांचना चाहता था।

+1

क्या आप बिन सीमाओं को सेट करने के बारे में पूछ रहे हैं, या "200+" के रूप में लेबल कैसे करें? आप ऊपरी सीमा को केवल 'the_data.max() + 1' या कुछ पर सेट कर सकते हैं, लेकिन मुझे लगता है कि यदि आप उस विशिष्ट प्रारूप को चाहते हैं तो आपको लेबल को मैन्युअल रूप से सेट करना होगा। – BrenBarn

+0

हाँ, मुझे लगता है कि यह एकमात्र तरीका है। –

उत्तर

4

कुछ ही दिनों प्रतीक्षा के बाद, अब भी कोई उत्तर पोस्ट - मुझे लगता है कि शायद इसलिए है क्योंकि वहाँ वास्तव में cut() आवरण समारोह लिखने की तुलना में इस दूसरे के चारों ओर कोई रास्ता नहीं है। मैं यहां अपना संस्करण पोस्ट कर रहा हूं और प्रश्न के उत्तर के रूप में चिह्नित कर रहा हूं। अगर नए जवाब आते हैं तो मैं बदल दूंगा।

def my_cut (x, bins, 
      lower_infinite=True, upper_infinite=True, 
      **kwargs): 
    r"""Wrapper around pandas cut() to create infinite lower/upper bounds with proper labeling. 

    Takes all the same arguments as pandas cut(), plus two more. 

    Args : 
     lower_infinite (bool, optional) : set whether the lower bound is infinite 
      Default is True. If true, and your first bin element is something like 20, the 
      first bin label will be '<= 20' (depending on other cut() parameters) 
     upper_infinite (bool, optional) : set whether the upper bound is infinite 
      Default is True. If true, and your last bin element is something like 20, the 
      first bin label will be '> 20' (depending on other cut() parameters) 
     **kwargs : any standard pandas cut() labeled parameters 

    Returns : 
     out : same as pandas cut() return value 
     bins : same as pandas cut() return value 
    """ 

    # Quick passthru if no infinite bounds 
    if not lower_infinite and not upper_infinite: 
     return pd.cut(x, bins, **kwargs) 

    # Setup 
    num_labels  = len(bins) - 1 
    include_lowest = kwargs.get("include_lowest", False) 
    right   = kwargs.get("right", True) 

    # Prepend/Append infinities where indiciated 
    bins_final = bins.copy() 
    if upper_infinite: 
     bins_final.insert(len(bins),float("inf")) 
     num_labels += 1 
    if lower_infinite: 
     bins_final.insert(0,float("-inf")) 
     num_labels += 1 

    # Decide all boundary symbols based on traditional cut() parameters 
    symbol_lower = "<=" if include_lowest and right else "<" 
    left_bracket = "(" if right else "[" 
    right_bracket = "]" if right else ")" 
    symbol_upper = ">" if right else ">=" 

    # Inner function reused in multiple clauses for labeling 
    def make_label(i, lb=left_bracket, rb=right_bracket): 
     return "{0}{1}, {2}{3}".format(lb, bins_final[i], bins_final[i+1], rb) 

    # Create custom labels 
    labels=[] 
    for i in range(0,num_labels): 
     new_label = None 

     if i == 0: 
      if lower_infinite: 
       new_label = "{0} {1}".format(symbol_lower, bins_final[i+1]) 
      elif include_lowest: 
       new_label = make_label(i, lb="[") 
      else: 
       new_label = make_label(i) 
     elif upper_infinite and i == (num_labels - 1): 
      new_label = "{0} {1}".format(symbol_upper, bins_final[i]) 
     else: 
      new_label = make_label(i) 

     labels.append(new_label) 

    # Pass thru to pandas cut() 
    return pd.cut(x, bins_final, labels=labels, **kwargs) 
+1

ग्रेट! क्या आपने अगले पांडस संस्करण के लिए अपना कोड प्रस्तावित किया है? – Manuel

+0

वाह, मैंने ऐसा कभी नहीं सोचा था। मुझे लगता है कि मैं कोशिश करूंगा - धन्यवाद! –

6

आप float("inf") ऊपरी सीमा के रूप में और -float("inf") डिब्बे सूची में कम बाध्य के रूप में उपयोग कर सकते हैं। यह NaN मानों को हटा देगा।

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