2014-07-09 46 views
38

我有一個熊貓數據框與混合類型的列,我想申請sklearn的min_max_scaler到一些列。理想情況下,我想做這些轉換,但還沒有想出一個辦法。我寫了下面的代碼:熊貓dataframe列與sklearn縮放

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

我很困惑爲什麼要通過一系列的縮放失敗。在上面我完整的工作代碼中,我曾希望將一個系列傳遞給縮放器,然後將dataframe列設置爲縮放系列。我已經看到這個問題問了其他幾個地方,但沒有找到一個好的答案。任何幫助瞭解這裏發生的事情將不勝感激!

+1

它的工作原理)'?訪問'values'屬性會返回一個numpy數組,因爲某些原因,scikit learn api會正確地調用正確的方法,使得pandas返回一個numpy數組,有時它不會。 – EdChum

+0

熊貓的數據框是相當複雜的對象,約定不符合scikit-learn的約定。如果你將所有東西都轉換成NumPy數組,scikit-learn可以更容易地處理。 –

+0

@edChum - 'bad_output = in_max_scaler.fit_transform(dfTest ['A']。values)'也不起作用。 @larsmans - 是的,我曾想過要沿着這條路走下去,這似乎很麻煩。我不知道Pandas是否可以將完整的數據框傳遞給sklearn函數,但不是一個系列。我對數據框的理解是它是一系列的字典。閱讀「Python for Data Analysis」一書,它指出熊貓建立在numpy之上,以便在以NumPy爲中心的應用程序中使用。 – flyingmeatball

回答

44

我不知道如果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 
+3

整潔! df [df.columns] = scaler.fit_transform(df [df.columns])' – citynorman

+0

我知道這是從原始日期開始的延遲評論,但爲什麼dfTest [['A']中有兩個方括號? ,'B']]?我可以看到它不支持單支架,但無法理解原因。 –

+2

@RajeshThevar外括號是大熊貓的典型選擇符括號,它告訴大熊貓從數據框中選擇一列。內括號表示一個列表。你正在將一個列表傳遞給熊貓選擇器。如果只使用單括號 - 一列名稱後跟另一列名稱,用逗號分隔 - 熊貓解釋這一點,就好像您試圖從具有多級列的數據框中選擇列一樣(MultiIndex),並會拋出一個鍵錯誤。 – ken

3

你只能使用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 
+3

我知道我可以在熊貓中做到這一點,但我可能想要最終應用一種不太容易寫出自己的sklearn方法。我更感興趣的是弄清楚爲什麼應用系列不能像我期望的那樣工作,而不是我想出一個更簡單的解決方案。我的下一步將是運行一個RandomForestRegressor,並且我想確保我理解Pandas和sklearn是如何協同工作的。 – flyingmeatball

16

喜歡這個?

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。它應該如何更新? – pir

+0

下面的答案沒有警告 – wi3o

+0

查看@ LetsPlayYahtzee的答案低於 – AJP

4

在皮爾的評論 - .apply(lambda el: scale.fit_transform(el))方法將產生以下警告:

DeprecationWarning:作爲數據傳遞1d數組已被棄用在0.17 ,並將0.19提高ValueError。如果數據包含單個要素,則使用 X.reshape(-1,1)重整數據,如果數據包含單個要素,則使用X.reshape(1,-1) 重整數據。

轉換列以numpy的陣列應該做的工作(我喜歡StandardScaler):

如果你這樣做`bad_output = min_max_scaler.fit_transform(dfTest [ 'A']值
from sklearn.preprocessing import StandardScaler 
scale = StandardScaler() 

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