2014-09-11 18 views
15

में लापता मूल्यों के साथ इन्स को निर्यात करना सीएसवी को पांडस डेटाफ्रेम सहेजते समय, कुछ पूर्णांक फ्लोट में परिवर्तित हो रहे हैं। ऐसा होता है जहां फ्लोट के कॉलम में मूल्य गुम हैं (np.nan)।पांडस

क्या इससे बचने का कोई आसान तरीका है? (विशेष रूप से एक स्वचालित तरीके से -। मैं अक्सर विभिन्न डेटा प्रकार के कई कॉलम के साथ सौदा)

उदाहरण के लिए

import pandas as pd 
import numpy as np 
df = pd.DataFrame([[1,2],[3,np.nan],[5,6]], 
        columns=["a","b"], 
        index=["i_1","i_2","i_3"]) 
df.to_csv("file.csv") 

पैदावार

,a,b 
i_1,1,2.0 
i_2,3, 
i_3,5,6.0 

मैं प्राप्त करना चाहते हैं क्या

है
,a,b 
i_1,1,2 
i_2,3, 
i_3,5,6 

संपादित करें: मैं Support for integer NA - Pandas Caveats and Gotchas से पूरी तरह से अवगत हूं। प्रश्न यह है कि एक अच्छा कामकाज क्या है (विशेष रूप से अगर विभिन्न प्रकार के कई अन्य कॉलम हैं और मुझे पहले से पता नहीं है कि "पूर्णांक" कॉलम में मूल्य गुम हैं)।

+2

क्यों यह कोई मुद्दा है , इनट्स के लिए 'NaN' का प्रतिनिधित्व करने का कोई तरीका नहीं है इसलिए फ़्लोट में रूपांतरण। आपको 'NaN' मानों को किसी चीज़ के साथ प्रतिस्थापित करना होगा जिसे' 0' की तरह int के रूप में प्रदर्शित किया जा सकता है, या स्ट्रिंग में कनवर्ट किया जा सकता है और 'nan' स्ट्रिंग को खाली मान के साथ प्रतिस्थापित कर सकता है और फिर – EdChum

+1

@EdChum निर्यात करता है, मुझे पता है कि' NaN' तैर रहे हैं। बस यह कष्टप्रद है कि "गायब int" नहीं है (डेटा परिप्रेक्ष्य से - एक लापता क्षेत्र एक गुम फ़ील्ड है; लापता फ्लोट के बारे में कुछ खास नहीं है)। बात यह है कि मैं एक लापता int को '0' के रूप में निर्यात नहीं करना चाहता, लेकिन एक खाली क्षेत्र के रूप में (कुछ अनुप्रयोगों के लिए मैं लापता इंक को '-1' में परिवर्तित करता हूं, लेकिन दूसरों के लिए यह समस्याग्रस्त हो सकता है)। –

+0

@PiotrMigdal मुझे लगता है कि उस मामले में आपका एकमात्र शॉट स्ट्रिंग में कनवर्ट करना है और खाली स्ट्रिंग के साथ नैन भरना है, जैसा कि पहले से ही – Korem

उत्तर

5

float_format = '%.12g' का उपयोग करते हुए अंदर to_csv समारोह एक हल मेरे लिए इसी तरह की समस्या।यह अप करने के लिए 12 महत्वपूर्ण अंक के साथ वैध तैरता के लिए दशमलव रखती है, बल्कि ints NaN के की मौजूदगी से तैरता के लिए मजबूर किया जा रहा के लिए उन्हें चला जाता है:

In [4]: df 
Out[4]: 
    a b 
i_1 1 2.0 
i_2 3 NaN 
i_3 5.9 6.0 

In [5]: df.to_csv('file.csv', float_format = '%.12g') 

आउटपुट है:

, a, b 
i_1, 1, 2 
i_2, 3, 
i_3, 5.9, 6 
2

@EdChum के सुझाव टिप्पणी अच्छा है, आप भी float_format तर्क इस्तेमाल कर सकते हैं

In [28]: a 
Out[28]: 
    a b 
0 0 1 
1 1 NaN 
2 2 3 
In [31]: a.to_csv(r'c:\x.csv', float_format = '%.0f') 

(docs में देखें) बाहर देता है:

,a,b 
0,0,1 
1,1, 
2,2,3 
+0

सामान्य में मेरे पास कई कॉलम हैं। मैं "सामान्य फ्लोट" को '% .0f''' के रूप में प्रारूपित नहीं करना चाहता हूं। मैं केवल 'int '(' np.nan 'के साथ मिश्रित करना चाहता हूं, जो दुख की बात है)' '% .0f''' के रूप में। –

4

मैं विस्तार हो रहा हूँ उम्मीदवार यह सुनिश्चित करने के लिए यहां नमूना डेटा सुनिश्चित कर रहे हैं कि आप जिन स्थितियों से निपट रहे हैं:

df = pd.DataFrame([[1.1,2,9.9,44,1.0], 
        [3.3,np.nan,4.4,22,3.0], 
        [5.5,8,np.nan,66,4.0]], 
        columns=list('abcde'), 
        index=["i_1","i_2","i_3"]) 

     a b c d e 
i_1 1.1 2 9.9 44 1 
i_2 3.3 NaN 4.4 22 3 
i_3 5.5 8 NaN 66 4 

df.dtypes 

a float64 
b float64 
c float64 
d  int64 
e float64 

मुझे लगता है कि यदि आप एक सामान्य समाधान चाहते हैं, तो इसे पांडों के कारण स्पष्ट रूप से कोडित किया जाना चाहिए क्योंकि एनएन को इंट कॉलम में अनुमति नहीं दी जा रही है। मैं यहां नीचे जो करता हूं वह पूर्णांक मान (क्योंकि हम वास्तव में प्रकार की जांच नहीं कर सकते हैं क्योंकि वे NaNs में फ़्लोट करने के लिए पुनरावृत्ति हो जाएंगे), और यदि यह एक पूर्णांक मान है तो स्ट्रिंग प्रारूप में कनवर्ट करें 'NAN' से '' (खाली) में कनवर्ट करें। बेशक, यह नहीं है कि आप आउटपुट से पहले अंतिम चरण के अलावा पूर्णांक को स्टोर करना चाहते हैं।

for col in df.columns: 
    if any(df[col].isnull()): 
     tmp = df[col][ df[col].notnull() ] 
     if all(tmp.astype(int).astype(float) == tmp.astype(float)): 
      df[col] = df[col].map('{:.0F}'.format).replace('NAN','') 

df.to_csv('x.csv') 

यहाँ आउटपुट फ़ाइल है और यह भी यह कैसा अगर आप पांडा में वापस इसे पढ़ा है, हालांकि यह करने के उद्देश्य से शायद है अन्य संख्यात्मक पैकेज में इसे पढ़ने के लिए लग रहा है है।

%more x.csv 

,a,b,c,d,e 
i_1,1.1,2,9.9,44,1.0 
i_2,3.3,,4.4,22,3.0 
i_3,5.5,8,,66,4.0 

pd.read_csv('x.csv') 

    Unnamed: 0 a b c d e 
0  i_1 1.1 2 9.9 44 1 
1  i_2 3.3 NaN 4.4 22 3 
2  i_3 5.5 8 NaN 66 4 
+0

धन्यवाद! समझ में आता है; यद्यपि, फिर भी यह फ़्लोट्स को घुमाता है जो इंट्स के पूर्णांक मान होते हैं (मानों के साथ कॉलम पर विचार करें [1.0, -5.0, 3.0] ')। फिर भी, मैं जो देखता हूं वह यह है कि सभी प्रविष्टियों के एकल 'एनपीएनएन' परिवर्तन प्रकार जोड़ते हैं, इसलिए मूल को पुनर्प्राप्त करने की कोई संभावना नहीं है। :/इस मामले में मुझे उत्सुकता है कि कॉलम कास्टिंग से बचना संभव है (उदा। 'ऑब्जेक्ट' प्रकार और तत्वों के मिश्रित प्रकार)। संपादित करें: ऐसा लगता है कि 'डेटाफ्रेम' या 'low_memory = गलत' बनाने के दौरान 'dtype = 'object'' सेटिंग को चाल चलती है। –

+0

@PiotrMigdal बस संपादित, एक नज़र डालें। प्रश्न का पहला भाग 'अगर कोई है (डीएफ [कोल] .isnull()) के साथ तय किया जाना चाहिए: '(एक नया कॉलम भी जोड़ा गया)। मैं प्रश्न के दूसरे भाग को समझ नहीं पा रहा हूं। केवल ऑब्जेक्ट्स को मिश्रित किया जा सकता है, संख्याओं को संग्रहित किया जा सकता है क्योंकि ऑब्जेक्ट्स हमेशा अंतिम उपाय होना चाहिए (हालांकि इस तरह के मामले में, मुझे लगता है) क्योंकि अंकीय प्रदर्शन इंक/फ्लोट की तुलना में वस्तुओं के साथ कहीं भी बदतर होगा। – JohnE

5

यह स्निपेट वह करता है जो आप चाहते हैं और इसे करने में अपेक्षाकृत कुशल होना चाहिए।

import numpy as np 
import pandas as pd 

EPSILON = 1e-9 

def _lost_precision(s): 
    """ 
    The total amount of precision lost over Series `s` 
    during conversion to int64 dtype 
    """ 
    try: 
     return (s - s.fillna(0).astype(np.int64)).sum() 
    except ValueError: 
     return np.nan 

def _nansafe_integer_convert(s): 
    """ 
    Convert Series `s` to an object type with `np.nan` 
    represented as an empty string "" 
    """ 
    if _lost_precision(s) < EPSILON: 
     # Here's where the magic happens 
     as_object = s.fillna(0).astype(np.int64).astype(np.object) 
     as_object[s.isnull()] = "" 
     return as_object 
    else: 
     return s 


def nansafe_to_csv(df, *args, **kwargs): 
    """ 
    Write `df` to a csv file, allowing for missing values 
    in integer columns 

    Uses `_lost_precision` to test whether a column can be 
    converted to an integer data type without losing precision. 
    Missing values in integer columns are represented as empty 
    fields in the resulting csv. 
    """ 
    df.apply(_nansafe_integer_convert).to_csv(*args, **kwargs) 

हम एक सरल DataFrame जो सभी ठिकानों को कवर करना चाहिए के साथ इस परीक्षण कर सकते हैं:

In [75]: df = pd.DataFrame([[1,2, 3.1, "i"],[3,np.nan, 4.0, "j"],[5,6, 7.1, "k"]] 
        columns=["a","b", "c", "d"], 
        index=["i_1","i_2","i_3"]) 
In [76]: df 
Out[76]: 
    a b c d 
i_1 1 2 3.1 i 
i_2 3 NaN 4.0 j 
i_3 5 6 7.1 k 

In [77]: nansafe_to_csv(df, 'deleteme.csv', index=False) 

निम्नलिखित में से कौन csv फ़ाइल का उत्पादन:

a,b,c,d 
1,2,3.1,i 
3,,4.0,j 
5,6,7.1,k 
+0

काम करता है, लेकिन 'फिल्ना (0)' की भूमिका क्या है? यह अनावश्यक लगता है। –

+0

ऐसा इसलिए है क्योंकि 'int64' में कनवर्ट करना काम नहीं करता है यदि आपके पास कॉलम में' नैन 'है। (हालांकि यह इसके बिना काम करता है, शायद मैं इसे बाहर ले जाऊंगा ...) – LondonRob