2014-07-09 46 views
38

Tôi có một khung dữ liệu gấu trúc với các cột loại hỗn hợp và tôi muốn áp dụng min_max_scaler của sklearn cho một số cột. Lý tưởng nhất, tôi muốn thực hiện các phép biến đổi này tại chỗ, nhưng chưa tìm ra cách để làm điều đó. Tôi đã viết mã sau hoạt động:pandas dataframe cột mở rộng với 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 

Tôi tò mò nếu đây là cách tốt nhất/hiệu quả nhất để thực hiện chuyển đổi này. Có cách nào tôi có thể sử dụng df.apply đó sẽ là tốt hơn?

Tôi cũng ngạc nhiên khi tôi không thể lấy mã sau đây để làm việc:

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

Nếu tôi vượt qua toàn bộ một dataframe để scaler nó hoạt động:

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

Tôi đang bối rối tại sao vượt qua một loạt các scaler thất bại. Trong mã làm việc đầy đủ của tôi ở trên tôi đã hy vọng chỉ cần vượt qua một loạt để scaler sau đó thiết lập cột dataframe = để loạt thu nhỏ. Tôi đã nhìn thấy câu hỏi này hỏi một vài nơi khác, nhưng không tìm thấy câu trả lời hay. Bất kỳ sự trợ giúp nào hiểu được những gì đang xảy ra ở đây sẽ được đánh giá cao!

+1

Liệu nó có tác dụng nếu bạn làm điều này 'bad_output = min_max_scaler.fit_transform (dfTest [ 'A'] giá trị.) '? việc truy cập thuộc tính 'values' trả về một mảng có nhiều mảng, vì một số lý do đôi khi scikit tìm hiểu api sẽ gọi đúng phương thức làm cho gấu trúc trả về một mảng có nhiều mảng và đôi khi nó không thành công. – EdChum

+0

Các khung dữ liệu của Pandas là các đối tượng khá phức tạp với các quy ước không phù hợp với quy ước của scikit-learn. Nếu bạn chuyển đổi mọi thứ thành các mảng NumPy, việc học bằng scikit sẽ dễ dàng hơn nhiều khi làm việc. –

+0

@edChum - 'bad_output = in_max_scaler.fit_transform (giá trị dfTest ['A'].)' Cũng không hoạt động. @ larsmans - vâng tôi đã nghĩ về việc đi xuống con đường này, nó chỉ có vẻ như một rắc rối. Tôi không biết nếu nó là một lỗi hay không mà Pandas có thể vượt qua một dataframe đầy đủ đến một chức năng sklearn, nhưng không phải là một loạt. Sự hiểu biết của tôi về một dataframe là nó là một dict của series.Đọc trong cuốn sách "Python để phân tích dữ liệu", nó nói rằng gấu trúc được xây dựng trên đầu trang của numpy để làm cho nó dễ sử dụng trong các ứng dụng NumPy-centric. – flyingmeatball

Trả lời

44

Tôi không chắc chắn nếu phiên bản trước của pandas ngăn cản này nhưng bây giờ đoạn sau hoạt động hoàn hảo đối với tôi và tạo ra chính xác những gì bạn muốn mà không cần phải sử dụng 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

Gọn gàng! Một phiên bản tổng quát hơn 'df [df.columns] = scaler.fit_transform (df [df.columns])' – citynorman

+0

Tôi biết đây là nhận xét bị trì hoãn từ ngày ban đầu, nhưng tại sao có hai dấu ngoặc vuông trong dfTest [['A' , 'B']]? Tôi có thể thấy nó không hoạt động với một khung, nhưng không thể hiểu được lý do. –

+2

@RajeshThevar Dấu ngoặc bên ngoài là dấu ngoặc đơn điển hình của gấu trúc, nói cho gấu trúc chọn cột từ khung dữ liệu. Các dấu ngoặc bên trong chỉ ra một danh sách. Bạn đang chuyển danh sách tới bộ chọn gấu trúc. Nếu bạn chỉ sử dụng dấu ngoặc đơn - với một tên cột theo sau là tên khác, được phân tách bằng dấu phẩy - gấu trúc diễn giải điều này như thể bạn đang cố gắng chọn cột từ một khung dữ liệu có cột nhiều cấp (multiIndex) và sẽ ném một keyerror . – ken

3

Bạn có thể làm điều đó bằng pandas chỉ:

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

Tôi biết rằng tôi có thể làm điều đó chỉ trong gấu trúc, nhưng tôi có thể muốn cuối cùng áp dụng một phương pháp sklearn khác mà không phải là dễ dàng để viết bản thân mình. Tôi quan tâm nhiều hơn trong việc tìm ra lý do tại sao áp dụng cho một loạt không hoạt động như tôi mong đợi hơn là tôi đang nghĩ ra một giải pháp đơn giản hơn. Bước tiếp theo của tôi là chạy một RandomForestRegressor, và tôi muốn chắc chắn rằng tôi hiểu Pandas và sklearn làm việc cùng nhau như thế nào. – flyingmeatball

16

Giống như này?

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

Tôi nhận được một loạt các Khử từ khi tôi chạy tập lệnh này. Làm thế nào nó nên được cập nhật? – pir

+0

Câu trả lời bên dưới hoạt động mà không có cảnh báo – wi3o

+0

Xem câu trả lời của @ LetsPlayYahtzee bên dưới – AJP

4

Vì nó đã được đề cập trong nhận xét của pir - phương pháp .apply(lambda el: scale.fit_transform(el)) sẽ đưa ra cảnh báo sau:

Khước từThời gian: Truyền mảng 1d vì dữ liệu không được dùng nữa trong 0,17 và sẽ tăng ValueError ở 0,19. Định hình lại dữ liệu của bạn bằng cách sử dụng X.reshape (-1, 1) nếu dữ liệu của bạn có một tính năng hoặc X.reshape (1, -1) nếu nó chứa một mẫu duy nhất.

Chuyển đổi các cột của bạn để NumPy mảng nên thực hiện công việc (tôi thích StandardScaler):

from sklearn.preprocessing import StandardScaler 
scale = StandardScaler() 

dfTest[['A','B','C']] = scale.fit_transform(dfTest[['A','B','C']].as_matrix()) 
Các vấn đề liên quan