在PyODPS DataFrame自定義函數中使用pandas、scipy和scikit-learn

背景

PyODPS DataFrame 提供了相似 pandas 的接口,來操做 ODPS 數據,同時也支持在本地使用 pandas,和使用數據庫來執行html

PyODPS DataFrame 除了支持相似 pandas 的 map 和 apply 方法,也提供了 MapReduce API 來擴展 pandas 語法以適應大數據環境。python

PyODPS 的自定義函數是序列化到 MaxCompute 上執行的,MaxCompute 的 Python 環境只包含了 numpy 這一個第三方包,用戶經常問的問題是,如何在自定義函數裏使用 pandas、scipy 或者 scikit-learn 這樣的包含c代碼的庫?linux

如今,MaxCompute 在 sprint 27 及更高版本的 isolation,讓在自定義函數中使用這些包成爲可能。同時,
PyODPS也須要至少0.7.4版本 。接下來我會詳細介紹使用步驟。sql

步驟

上傳第三方包(只需作一次)

這個步驟只須要作一次,當 MaxCompute 資源裏有了這些包,這一步直接跳過。數據庫

如今這些主流的 Python 包都提供了 whl 包,提供了各平臺包含二進制文件的包,所以找到能在 MaxCompute 上能運行的包是第一步。api

其次,要想在 MaxCompute 上運行,須要包含全部的依賴包,這個是比較繁瑣的。咱們能夠看下各個包的依賴狀況(刪除表示已經包含)session

包名 依賴
pandas numpy, python-dateutil, pytz, six
scipy numpy
scikit-learn numpy, scipy

因此,咱們一共須要上傳 python-dateutil、pytz、pandas、scipy、sklearn、six 這六個包,就能保證 pandas、scipy 和 scikit-learn 可用。app

咱們直接經過 http://mirrors.aliyun.com/pypi/simple 來找包。首先是 python-dateutils:http://mirrors.aliyun.com/pypi/simple/python-dateutil/ 。咱們找到最新版,這個包是純 Python 的包,咱們找到最新版的 zip 包,python-dateutil-2.6.0.zip,下載。函數

重命名爲 python-dateutil.zip,經過 MaxCompute Console 上傳資源。大數據

add archive python-dateutil.zip;

pytz 同樣,找到 pytz-2017.2.zip。上傳不表。

six 找到 six-1.11.0.tar.gz

接下來,是pandas,對於這種包含c的包,咱們必定要找 名字中包含cp27-cp27m-manylinux1_x86_64 的whl包,這樣才能在 MaxCompute 上正確執行。所以,這樣咱們找到最新版的包是:pandas-0.20.2-cp27-cp27m-manylinux1_x86_64.whl

這裏咱們把後綴改爲zip,上傳。

add archive pandas.zip;

其餘包也是同樣,所以,咱們把它們都列出來:

包名 文件名 上傳資源名
python-dateutil python-dateutil-2.6.0.zip python-dateutil.zip
pytz pytz-2017.2.zip pytz.zip
six six-1.11.0.tar.gz six.tar.gz
pandas pandas-0.20.2-cp27-cp27m-manylinux1_x86_64.zip pandas.zip
scipy scipy-0.19.0-cp27-cp27m-manylinux1_x86_64.zip scipy.zip
scikit-learn scikit_learn-0.18.1-cp27-cp27m-manylinux1_x86_64.zip sklearn.zip

至此,所有包上傳都已完成。

固然,咱們所有上傳也可使用 PyODPS 的資源上傳接口來完成,一樣只須要操做一遍便可。至於用哪一個,看我的喜愛了。

編寫代碼驗證

咱們寫一個簡單的函數,裏面用到了全部的庫,最好是在函數裏來 import 這些第三方庫。

def test(x):
    from sklearn import datasets, svm
    from scipy import misc
    import numpy as np

    iris = datasets.load_iris()
    assert iris.data.shape == (150, 4)
    assert np.array_equal(np.unique(iris.target),  [0, 1, 2])

    clf = svm.LinearSVC()
    clf.fit(iris.data, iris.target)
    pred = clf.predict([[5.0, 3.6, 1.3, 0.25]])
    assert pred[0] == 0

    assert misc.face().shape is not None

    return x

這段代碼只是示例,目標是用到以上所說的全部的包。

寫完函數後,咱們寫一個簡單的 map,記住, 運行時要確保 isolation 打開 ,若是不在 project 級別打開,能夠在運行時打開,一個能夠設置全局的選項:

from odps import options

options.sql.settings = {'odps.isolation.session.enable': True}

也能夠在 execute 方法上指定本次執行打開 isolation。

一樣,咱們能夠在全局經過 options.df.libraries 指定用到的包,也能夠在 execute 時指定。這裏,咱們要指定全部的包,包括依賴。下面就是調用剛剛定義的函數的例子。

hints = {
    'odps.isolation.session.enable': True
}
libraries = ['python-dateutil.zip', 'pytz.zip', 'six.tar.gz', 'pandas.zip', 'scipy.zip', 'sklearn.zip']

iris = o.get_table('pyodps_iris').to_df()

print iris[:1].sepal_length.map(test).execute(hints=hints, libraries=libraries)

能夠看到,咱們的函數順利執行。

總結

對於要用到的第三方庫及其依賴,若是已經上傳,則能夠直接編寫代碼,並指定用到的 libraries 便可;不然,須要按照教程上傳第三方庫。

能夠看到,當第一步上傳包作事後,之後每次使用都是優雅的,只需指定 libraries 就能夠了。

原文連接

相關文章
相關標籤/搜索