पांडा में NaN के साथ रिक्त मान (सफेद स्थान) को बदलना


150

मैं पंडों के डेटाफ्रेम में सभी मानों को ढूंढना चाहता हूं जिसमें व्हाट्सएप (कोई भी मनमानी राशि) हो और उन मानों को NaNs से बदल दें।

किसी भी विचार यह कैसे सुधार किया जा सकता है?

मूल रूप से मैं इसे चालू करना चाहता हूं:

                   A    B    C
2000-01-01 -0.532681  foo    0
2000-01-02  1.490752  bar    1
2000-01-03 -1.387326  foo    2
2000-01-04  0.814772  baz     
2000-01-05 -0.222552         4
2000-01-06 -1.176781  qux     

इस मामले में:

                   A     B     C
2000-01-01 -0.532681   foo     0
2000-01-02  1.490752   bar     1
2000-01-03 -1.387326   foo     2
2000-01-04  0.814772   baz   NaN
2000-01-05 -0.222552   NaN     4
2000-01-06 -1.176781   qux   NaN

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

for i in df.columns:
    df[i][df[i].apply(lambda i: True if re.search('^\s*$', str(i)) else False)]=None

यह केवल उन क्षेत्रों के माध्यम से पुनरावृत्ति करके थोड़ा अनुकूलित किया जा सकता है जिनमें खाली तार हो सकते हैं:

if df[i].dtype == np.dtype('object')

लेकिन यह बहुत सुधार नहीं है

और अंत में, यह कोड टारगेट स्ट्रिंग्स को कोई नहीं सेट करता है, जो पंडों के कार्यों के साथ काम करता है fillna(), लेकिन यह पूर्णता के लिए अच्छा होगा यदि मैं वास्तव में NaNइसके बजाय सीधे सम्मिलित कर सकता हूं None


2
क्या आप वास्तव में चाहते हैं कि replaceएक रेगेक्स के साथ उपयोग करने में सक्षम हो ... (शायद यह एक सुविधा के रूप में अनुरोध किया जाना चाहिए)।
एंडी हेडन

3
मैंने इस सुविधा के लिए एक github मुद्दा बनाया: github.com/pydata/pandas/issues/2285 । PRs के लिए आभारी होंगे! :)
चांग शी

उन लोगों के लिए जो गायब होने के लिए बिल्कुल एक खाली चरित्र को चालू करना चाहते हैं, नीचे इस सरल समाधान को देखें
टेड पेट्रोउ

जवाबों:


198

मुझे लगता df.replace()है कि काम करता है, क्योंकि पांडा 0.13 :

df = pd.DataFrame([
    [-0.532681, 'foo', 0],
    [1.490752, 'bar', 1],
    [-1.387326, 'foo', 2],
    [0.814772, 'baz', ' '],     
    [-0.222552, '   ', 4],
    [-1.176781,  'qux', '  '],         
], columns='A B C'.split(), index=pd.date_range('2000-01-01','2000-01-06'))

# replace field that's entirely space (or empty) with NaN
print(df.replace(r'^\s*$', np.nan, regex=True))

पैदा करता है:

                   A    B   C
2000-01-01 -0.532681  foo   0
2000-01-02  1.490752  bar   1
2000-01-03 -1.387326  foo   2
2000-01-04  0.814772  baz NaN
2000-01-05 -0.222552  NaN   4
2000-01-06 -1.176781  qux NaN

जैसा कि टेमाक ने बताया, df.replace(r'^\s+$', np.nan, regex=True)यदि आपके वैध डेटा में सफेद स्थान हैं , तो इसका उपयोग करें।


1
रेगेक्स एक बूलियन ध्वज है। हो सकता है कि आप का मतलब pd.Series(["1", "#", "9", " .", None]).replace(r"( +\.)|#", "X", regex=True).valuesहै['1', 'X', '9', 'X', None]
patricksurry

2
2 साल के बाद, मैंने इसके लिए स्वीकृत उत्तर को बदल दिया है, अब यह पांडा इसका समर्थन करता है। धन्यवाद!
क्रिस क्लार्क

35
नोट : यदि आप NaN उपयोग के साथ बदलने के लिए बीच में जगह वाले तत्व नहीं चाहते हैंdf.replace(r'^\s+$', np.nan, regex=True)
Temak

7
मैंने इसका उपयोग करने की कोशिश की, लेकिन पता चला कि r '^ \ s * $' का उपयोग करने के लिए अभिव्यक्ति होनी चाहिए। बिना ^ और $ यह लगातार दो खाली के साथ किसी भी तार से मेल खाएगा। NaN में बदलने के लिए चीजों की सूची में खाली स्ट्रिंग "" को शामिल करने के लिए + से * तक बदल दिया गया
मास्टर दही

1
मैं अपने कोड में आपके समाधान की कोशिश कर रहा हूं, लेकिन इसका कोई प्रभाव नहीं है। मैं "एनर्जी [" एनर्जी सप्लाई "] की कोशिश कर रहा हूं। प्रतिस्थापित करें (to_replace =" ... ", value = np.NaN")। स्ट्रिंग को "..." को NaN मानों में बदलना चाहते हैं, लेकिन यह कुछ भी नहीं करता है और समान डेटाफ्रेम लौटाता है।
अर्चना जोशी

50

यदि आप केवल रिक्त स्थान और रिक्त स्थान को बदलना चाहते हैं, तो सही उत्तर है ! "

df = df.replace(r'^\s*$', np.nan, regex=True)

स्वीकृत उत्तर

df.replace(r'\s+', np.nan, regex=True)

एक खाली स्ट्रिंग को प्रतिस्थापित नहीं करता है!, आप अपने आप को दिए गए उदाहरण के साथ थोड़ा अद्यतन करके देख सकते हैं:

df = pd.DataFrame([
    [-0.532681, 'foo', 0],
    [1.490752, 'bar', 1],
    [-1.387326, 'fo o', 2],
    [0.814772, 'baz', ' '],     
    [-0.222552, '   ', 4],
    [-1.176781,  'qux', ''],         
], columns='A B C'.split(), index=pd.date_range('2000-01-01','2000-01-06'))

ध्यान दें, यह भी कि 'fo o' को Nan के साथ नहीं बदला गया है, हालांकि इसमें एक स्पेस है। आगे ध्यान दें, यह एक सरल:

df.replace(r'', np.NaN)

या तो काम नहीं करता है - इसे आज़माएं।


33

कैसा रहेगा:

d = d.applymap(lambda x: np.nan if isinstance(x, basestring) and x.isspace() else x)

applymapसमारोह dataframe के हर सेल में फ़ंक्शन लागू होता है।


कितना अच्छा सुधार है! मुझे रेट्रोस्पेक्ट में इसके बारे में सोचना चाहिए था, लेकिन किसी कारणवश बूलियन रिप्लेसमेंट करने पर लटका हुआ था। एक सवाल - क्या बेसस्ट्रिंग चेक बनाम बस स्ट्रेट (x) .isspace () करने का फायदा है?
क्रिस क्लार्क

1
@ क्रिस क्लार्क: या तो एक ठीक है, हालांकि मुझे लगता है कि isinstanceइच्छाशक्ति थोड़ी तेज होगी।
ब्रेनबार

13
उपरोक्त कोड में "बेसिस्ट्रिंग" का संदर्भ पायथन 3 में काम नहीं करेगा .... उस स्थिति में, इसके बजाय "str" ​​का उपयोग करने का प्रयास करें।
स्पाइक विलियम्स

4
ध्यान दें कि यह समाधान खाली तारों को प्रतिस्थापित नहीं करता है ''। खाली तार पर विचार करने के लिए, उपयोग करें:d = d.applymap(lambda x: np.nan if isinstance(x, basestring) and (not x or x.isspace()) else x)
tuomastik

18

मैंने यह किया है:

df = df.apply(lambda x: x.str.strip()).replace('', np.nan)

या

df = df.apply(lambda x: x.str.strip() if isinstance(x, str) else x).replace('', np.nan)

आप सभी str को स्ट्रिप कर सकते हैं, फिर खाली str को बदल सकते हैं np.nan


lambda x: x.str.strip () लैंबडा x होना चाहिए: x.strip ()? मामूली सुझाव: सामने .astype (str) जोड़ें, यह मेरे लिए अन्य डेटा समस्याओं को हल करता है। यह मेरे लिए काम करता है: df = df.apply ['column']। astype (str) .apply (लैम्ब्डा x: x.strip ())। प्रतिस्थापित करें ('', np.nan)
Wouter

कोड की दूसरी पंक्ति इंट / फ्लोट और स्ट्रिंग टाइप कॉलम दोनों को संभालती है। अच्छा लगा। टी.के.एस!
केट स्टोहर


5

यदि आप CSV फ़ाइल से डेटा निर्यात कर रहे हैं तो यह इस प्रकार सरल हो सकता है:

df = pd.read_csv(file_csv, na_values=' ')

यह डेटा फ़्रेम बनाने के साथ-साथ रिक्त मानों को Na के रूप में प्रतिस्थापित करेगा


2
एक अन्य विकल्प..उपयोगकर्ता परिसीमा के skipinitialspace=Trueबाद किसी भी व्हाट्सएप को भी हटा देता है जिससे किसी भी सफेद स्थान की लंबाई, खाली तारों के रूप में पढ़ी जा सकेगी nan। हालाँकि यदि आप कभी भी कारण के लिए प्रारंभिक रिक्त स्थान को बनाए रखना चाहते हैं तो यह विकल्प एक अच्छा विकल्प नहीं है।
राजशेखर रेड्डी

1
@RajshekarReddy कृपया आप इसे कहीं उत्तर के रूप में डाल सकते हैं, यह शानदार था!
User2321 8

2

एक बहुत तेज और सरल समाधान के लिए जहां आप एकल मूल्य के खिलाफ समानता की जांच करते हैं, आप maskविधि का उपयोग कर सकते हैं ।

df.mask(df == ' ')

1

ये सभी सही उत्तर के करीब हैं, लेकिन मैं आपके कोड को पढ़ने वाले अन्य लोगों के लिए सबसे पठनीय रहते हुए समस्या को हल करने के लिए नहीं कहूंगा। मैं कहता हूँ कि उत्तर ब्रेनबर्न के उत्तर का संयोजन है और उस उत्तर के नीचे tuomasttik की टिप्पणी है । BrenBarn का उत्तर बिल्डिन का उपयोग करता है isspace, लेकिन ओपी के अनुरोध के अनुसार, खाली तारों को हटाने का समर्थन नहीं करता है, और मैं इस बात का ध्यान रखना चाहूंगा कि अशक्त के साथ स्ट्रिंग की जगह के मानक उपयोग के मामले में।

मैंने इसे फिर से लिखा है .apply, इसलिए आप इसे pd.Seriesया तो कह सकते हैं pd.DataFrame


अजगर 3:

पूरी तरह से रिक्त स्थान के तारों या तारों को बदलने के लिए:

df = df.apply(lambda x: np.nan if isinstance(x, str) and (x.isspace() or not x) else x)

पूरी तरह से रिक्त स्थान के तार बदलने के लिए:

df = df.apply(lambda x: np.nan if isinstance(x, str) and x.isspace() else x)

अजगर 2 में इस का उपयोग करने के लिए आपको बदलना भी होगा strसाथ basestring

अजगर 2:

पूरी तरह से रिक्त स्थान के तारों या तारों को बदलने के लिए:

df = df.apply(lambda x: np.nan if isinstance(x, basestring) and (x.isspace() or not x) else x)

पूरी तरह से रिक्त स्थान के तार बदलने के लिए:

df = df.apply(lambda x: np.nan if isinstance(x, basestring) and x.isspace() else x)

1

इसने मेरे लिए काम किया। जब मैं अपनी सीएसवी फ़ाइल आयात करता हूं तो मैंने na_values ​​= '' जोड़ा। रिक्त स्थान डिफ़ॉल्ट NaN मानों में शामिल नहीं हैं।

df = pd.read_csv (filepath, na_values ​​= '')


0

आप इसे करने के लिए फ़िल्टर का उपयोग भी कर सकते हैं।

df = PD.DataFrame([
    [-0.532681, 'foo', 0],
    [1.490752, 'bar', 1],
    [-1.387326, 'foo', 2],
    [0.814772, 'baz', ' '],     
    [-0.222552, '   ', 4],
    [-1.176781,  'qux', '  '])
    df[df=='']='nan'
    df=df.astype(float)

इस कोड की प्रत्येक पंक्ति (डेटा सहित नहीं) दोषपूर्ण है।
जूलियस

0
print(df.isnull().sum()) # check numbers of null value in each column

modifiedDf=df.fillna("NaN") # Replace empty/null values with "NaN"

# modifiedDf = fd.dropna() # Remove rows with empty values

print(modifiedDf.isnull().sum()) # check numbers of null value in each column

0

यह एक सुरुचिपूर्ण समाधान नहीं है, लेकिन जो काम करने लगता है वह XLSX को बचा रहा है और फिर इसे वापस आयात कर रहा है। इस पृष्ठ पर अन्य समाधान मेरे लिए काम नहीं करते थे, अनिश्चित क्यों।

data.to_excel(filepath, index=False)
data = pd.read_excel(filepath)
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.