पांडा डेटाफ्रेम कॉलम स्केलेन के साथ स्केलिंग करते हैं


137

मेरे पास मिश्रित प्रकार के स्तंभों के साथ एक पांडा डेटाफ़्रेम है, और मैं कुछ स्तंभों में स्केलेर के min_max_scaler को लागू करना चाहूंगा। आदर्श रूप में, मैं इन परिवर्तनों को जगह में करना चाहूंगा, लेकिन अभी तक ऐसा करने का कोई तरीका नहीं निकला है। मैंने निम्नलिखित कोड लिखा है जो काम करता है:

import pandas as pd
import numpy as np
from sklearn import preprocessing

scaler = preprocessing.MinMaxScaler()

dfTest = pd.DataFrame({'A':[14.00,90.20,90.95,96.27,91.21],'B':[103.02,107.26,110.35,114.23,114.68], 'C':['big','small','big','small','small']})
min_max_scaler = preprocessing.MinMaxScaler()

def scaleColumns(df, cols_to_scale):
    for col in cols_to_scale:
        df[col] = pd.DataFrame(min_max_scaler.fit_transform(pd.DataFrame(dfTest[col])),columns=[col])
    return df

dfTest

    A   B   C
0    14.00   103.02  big
1    90.20   107.26  small
2    90.95   110.35  big
3    96.27   114.23  small
4    91.21   114.68  small

scaled_df = scaleColumns(dfTest,['A','B'])
scaled_df

A   B   C
0    0.000000    0.000000    big
1    0.926219    0.363636    small
2    0.935335    0.628645    big
3    1.000000    0.961407    small
4    0.938495    1.000000    small

मुझे उत्सुकता है कि क्या यह परिवर्तन करने के लिए पसंदीदा / सबसे कुशल तरीका है। वहाँ एक तरह से मैं df.apply का उपयोग कर सकता है कि बेहतर होगा?

मुझे आश्चर्य है कि मुझे काम करने के लिए निम्न कोड नहीं मिल सकता है:

bad_output = min_max_scaler.fit_transform(dfTest['A'])

अगर मैं स्केलर को पूरा डाटाफ्रेम पास करता हूं तो यह काम करता है:

dfTest2 = dfTest.drop('C', axis = 1) good_output = min_max_scaler.fit_transform(dfTest2) good_output

मैं उलझन में हूं कि स्केलर के लिए एक श्रृंखला पास करना क्यों विफल हो गया। ऊपर मेरे पूर्ण काम करने वाले कोड में मैंने स्केलर को एक श्रृंखला पास करने की उम्मीद की थी, फिर डेटाफ्रेम कॉलम = स्केल की गई श्रृंखला में सेट किया। मैंने देखा है कि यह प्रश्न कुछ अन्य स्थानों पर पूछा गया है, लेकिन इसका अच्छा उत्तर नहीं मिला है। किसी भी मदद को समझने के लिए यहाँ क्या हो रहा है बहुत सराहना की जाएगी!


1
यदि आप ऐसा करते हैं तो क्या यह काम करता है bad_output = min_max_scaler.fit_transform(dfTest['A'].values)? valuesविशेषता तक पहुँचने के लिए एक सुव्यवस्थित सरणी देता है, किसी कारण से कभी-कभी शिकंजी एप आपी को सही तरीके से सही तरीके से कॉल करेगा जो पांडा को एक सुपीरियर सरणी देता है और कभी-कभी ऐसा नहीं करता है।
एडचम

पंडों के डेटाफ़्रेम, सम्मेलनों के साथ काफी जटिल वस्तुएं हैं जो स्किटिट-लर्न के सम्मेलनों से मेल नहीं खाती हैं। अगर आप सब कुछ NumPy सरणियों में परिवर्तित करते हैं, तो scikit-learn से काम करना बहुत आसान हो जाता है।
फ्रेड फू

@edChum - bad_output = in_max_scaler.fit_transform(dfTest['A'].values)या तो काम नहीं किया। @larsmans - हाँ, मैं इस मार्ग के नीचे जाने के बारे में सोचा था, यह सिर्फ एक परेशानी की तरह लगता है। मुझे नहीं पता कि यह एक बग है या नहीं कि पंडों ने एक स्केलेर फ़ंक्शन को पूर्ण डेटाफ़्रेम पास किया है, लेकिन श्रृंखला नहीं। एक डेटाफ्रेम के बारे में मेरी समझ यह थी कि यह एक श्रंखला है। "पायथन फॉर डेटा एनालिसिस" पुस्तक में पढ़ते हुए, यह बताता है कि नुप्पा के शीर्ष पर पंडों का निर्माण किया गया है ताकि न्यूमपी-केंद्रित अनुप्रयोगों में उपयोग करना आसान हो सके।
फ्लाइंगमैटबॉल

जवाबों:


214

मुझे यकीन नहीं है कि अगर पिछले संस्करणों pandasने इसे रोका है लेकिन अब निम्नलिखित स्निपेट मेरे लिए पूरी तरह से काम करता है और बिल्कुल वही पैदा करता है जिसे आप उपयोग किए बिना चाहते हैंapply

>>> import pandas as pd
>>> from sklearn.preprocessing import MinMaxScaler


>>> scaler = MinMaxScaler()

>>> dfTest = pd.DataFrame({'A':[14.00,90.20,90.95,96.27,91.21],
                           'B':[103.02,107.26,110.35,114.23,114.68],
                           'C':['big','small','big','small','small']})

>>> dfTest[['A', 'B']] = scaler.fit_transform(dfTest[['A', 'B']])

>>> dfTest
          A         B      C
0  0.000000  0.000000    big
1  0.926219  0.363636  small
2  0.935335  0.628645    big
3  1.000000  0.961407  small
4  0.938495  1.000000  small

80
साफ! एक अधिक सामान्यीकृत संस्करणdf[df.columns] = scaler.fit_transform(df[df.columns])
शहरकर्मन

6
@RajeshThevar बाहरी कोष्ठक पांडा के विशिष्ट चयनकर्ता कोष्ठक हैं, जो पंडों को डेटाफ़्रेम से एक कॉलम का चयन करने के लिए कह रहे हैं। आंतरिक कोष्ठक एक सूची का संकेत देते हैं। आप पंडों के चयनकर्ता को एक सूची दे रहे हैं। यदि आप केवल एकल कोष्ठक का उपयोग करते हैं - एक स्तंभ नाम के साथ, उसके बाद एक अल्पविराम द्वारा अलग - पांडा इस तरह की व्याख्या करते हैं जैसे कि आप बहु-स्तरीय कॉलम (एक मल्टीइन्डेक्स) के साथ एक डेटाफ्रेम से एक स्तंभ का चयन करने का प्रयास कर रहे हैं और एक कीरोर फेंक देंगे। ।
केन

1
@ ken के उत्तर में जोड़ने के लिए यदि आप यह देखना चाहते हैं कि पांडा इस अनुक्रमणिका तर्क को कैसे लागू करते हैं और मानों का एक समूह सूची से अलग तरीके से व्याख्या किया जाएगा तो आप देख सकते हैं कि डेटाफ्रैम __getitem__विधि को कैसे लागू करता है। विशेष रूप से आप आपको ipython खोल सकते हैं और कर सकते हैं pd.DataFrame.__getitem__??; पंडों को पीडी के रूप में आयात करने के बाद;)
LetsPlayYahtzee

4
एक व्यावहारिक नोट: ट्रेन / परीक्षण डेटा विभाजन का उपयोग करने वालों के लिए, आप केवल अपने प्रशिक्षण डेटा पर फिट होना चाहेंगे, न कि आपके परीक्षण डेटा पर।
डेविड जे।

1
सभी टाइमस्टैम्प कॉलम को स्केल करने के लिए columns =df.columns.drop('timestamps') df[df.columns] = scaler.fit_transform(df[df.columns]
1919 से

19

ऐशे ही?

dfTest = pd.DataFrame({
           'A':[14.00,90.20,90.95,96.27,91.21],
           'B':[103.02,107.26,110.35,114.23,114.68], 
           'C':['big','small','big','small','small']
         })
dfTest[['A','B']] = dfTest[['A','B']].apply(
                           lambda x: MinMaxScaler().fit_transform(x))
dfTest

    A           B           C
0   0.000000    0.000000    big
1   0.926219    0.363636    small
2   0.935335    0.628645    big
3   1.000000    0.961407    small
4   0.938495    1.000000    small

3
इस स्क्रिप्ट को चलाने पर मुझे DeprecationWarnings का एक गुच्छा मिलता है। इसे कैसे अपडेट किया जाना चाहिए?
पीर

नीचे देखें @ LetsPlayYahtzee का जवाब
AJP

2
एक सरल संस्करण: dfTest [['A', 'B']] = dfTest [['A', 'B']] लागू करें (MinMaxScaler ()-fit_transform)
वी।

12

जैसा कि यह पीर की टिप्पणी में उल्लिखित है - .apply(lambda el: scale.fit_transform(el))विधि निम्नलिखित चेतावनी का उत्पादन करेगी:

DeprecationWarning: डेटा के रूप में 1d सरणियों को पास करना 0.17 में पदावनत है और 0.19 में ValueError बढ़ाएगा। यदि आपके डेटा में एकल सुविधा या X.reshape (1, -1) है, तो अपने नमूने का उपयोग करके अपने डेटा को फिर से आकार दें।

अपने कॉलम को सुन्न सरणियों में परिवर्तित करके काम करना चाहिए (मैं StandardScaler पसंद करता हूं):

from sklearn.preprocessing import StandardScaler
scale = StandardScaler()

dfTest[['A','B','C']] = scale.fit_transform(dfTest[['A','B','C']].as_matrix())

- नवंबर 2018 को संपादित करें (पांडा 0.23.4 के लिए परीक्षण किया गया ) -

के रूप में रोब मरे टिप्पणी में उल्लेख है, पांडा की वर्तमान (v0.23.4) संस्करण में .as_matrix()रिटर्न FutureWarning। इसलिए, इसे प्रतिस्थापित किया जाना चाहिए .values:

from sklearn.preprocessing import StandardScaler
scaler = StandardScaler()

scaler.fit_transform(dfTest[['A','B']].values)

- मई 2019 को संपादित करें (पांडा 0.24.2 के लिए परीक्षण किया गया ) -

जैसा कि joelostblom टिप्पणियों में उल्लेख करता है, "चूंकि 0.24.0, इसके .to_numpy()बजाय उपयोग करने की सिफारिश की गई है .values।"

अद्यतन उदाहरण:

import pandas as pd
from sklearn.preprocessing import StandardScaler
scaler = StandardScaler()
dfTest = pd.DataFrame({
               'A':[14.00,90.20,90.95,96.27,91.21],
               'B':[103.02,107.26,110.35,114.23,114.68],
               'C':['big','small','big','small','small']
             })
dfTest[['A', 'B']] = scaler.fit_transform(dfTest[['A','B']].to_numpy())
dfTest
      A         B      C
0 -1.995290 -1.571117    big
1  0.436356 -0.603995  small
2  0.460289  0.100818    big
3  0.630058  0.985826  small
4  0.468586  1.088469  small

1
के .valuesस्थान पर उपयोग अब एक के .as_matrix()रूप में as_matrix()देता है FutureWarning
रोब मूर्रे


10
df = pd.DataFrame(scale.fit_transform(df.values), columns=df.columns, index=df.index)

यह मूल्यह्रास चेतावनी के बिना काम करना चाहिए।


7

आप इसे pandasकेवल उपयोग करके कर सकते हैं :

In [235]:
dfTest = pd.DataFrame({'A':[14.00,90.20,90.95,96.27,91.21],'B':[103.02,107.26,110.35,114.23,114.68], 'C':['big','small','big','small','small']})
df = dfTest[['A', 'B']]
df_norm = (df - df.min()) / (df.max() - df.min())
print df_norm
print pd.concat((df_norm, dfTest.C),1)

          A         B
0  0.000000  0.000000
1  0.926219  0.363636
2  0.935335  0.628645
3  1.000000  0.961407
4  0.938495  1.000000
          A         B      C
0  0.000000  0.000000    big
1  0.926219  0.363636  small
2  0.935335  0.628645    big
3  1.000000  0.961407  small
4  0.938495  1.000000  small

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

5
यह उत्तर खतरनाक है क्योंकि df.max() - df.min()0 हो सकता है, एक अपवाद के लिए अग्रणी। इसके अलावा, df.min()दो बार गणना की जाती है जो अक्षम है। ध्यान दें कि df.ptp()इसके बराबर है df.max() - df.min()
एक्यूमेनस

3

मुझे पता है कि यह एक बहुत पुरानी टिप्पणी है, लेकिन फिर भी:

एकल ब्रैकेट का उपयोग करने के बजाय (dfTest['A']), डबल ब्रैकेट का उपयोग करें(dfTest[['A']])

अर्थात: min_max_scaler.fit_transform(dfTest[['A']])

मुझे विश्वास है कि यह वांछित परिणाम देगा।

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