2014-07-09 47 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())