數據科學從業者常見的不良小習慣

圖片描述

文章選自:Medium

                             做者:Norm Niemer

                             京東雲開發者社區編譯

數據科學家是「比任何軟件工程師都更擅長統計數據,比統計學家更擅長軟件工程的一批人」。許多數據科學家都有統計學背景,同時也有着一些軟件工程方面經驗。我是一名在Stackoverflow上使用Python代碼排名前1%的高級數據科學家,並與許多(初級)數據科學家們一塊兒工做。在這個過程當中,我發現你們其實都或多或少有着一些不太好的小習慣,如下是我列出的10個數據科學從業者常見的不良習慣列表。html

1.沒有共享代碼中引用的數據

數據科學須要代碼和數據,這點毋庸置疑。所以,若是別人要查證到你的結果,他們就須要訪問數據。這看起來彷佛很基本,但不少人都會忘記共享他們代碼中引用數據。python

1import pandas as pd
2df1 = pd.read_csv('file-i-dont-have.csv') # fails
3do_stuff(df)

解決方案:使用d6tpipe(https://github.com/d6t/d6tpipe)來共享您的代碼數據文件或將其上傳到S3/Web/Google Drive等,或者保存到數據庫也能夠。這樣作的目的在於能夠便於你們進行文件檢索。(Notice:但不要將它們添加到Git,詳情見下文)。git

2.硬編碼沒法訪問的路徑

與錯誤1相似,若是您的硬編碼路徑別人無權訪問,那他們則沒法運行您的代碼而且必須查看許多地方以手動更改路徑。🙄🙄🙄!github

1import pandas as pd
2df = pd.read_csv('/path/i-dont/have/data.csv') # fails
3do_stuff(df)
4# or 
5impor os
6os.chdir('c:\\Users\\yourname\\desktop\\python') # fails

解決方案:使用相對路徑、全局路徑配置變量或用d6tpipe使您的數據易於訪問。數據庫

3.將數據與代碼混在一塊兒

有人會問,因爲數據科學代碼須要數據,所以爲何不將它們轉存到同一目錄中呢?但這也意味着,當你在使用它的時候,你的圖像、報告和其餘垃圾也都會存在裏面。Emm……能夠說是一團糟呢!編程

1├── data.csv
2├── ingest.py
3├── other-data.csv
4├── output.png
5├── report.html
6└── run.py

解決方案:將您的目錄進行分類,如數據、報告、代碼等。具體請參閱Cookiecutter Data Science或d6tflow項目模板(https://github.com/d6t/d6tflo...)。(可用本文第1點中提到的工具來存儲和共享數據。)微信

4. 使用Git提交源代碼數據

大多數人如今用版本控制系統來管理他們的代碼(若是你不這樣的話,那將會是另外一個錯誤!!🙂)。在嘗試共享數據時,可能很容易將數據文件添加到版本控制中。這對於很是小的文件是能夠的,可是git沒有針對數據進行優化,尤爲是大文件。架構

1git add data.csv

解決方案:建議使用第1點中提到的工具來存儲和共享數據。若是您真的想要版本控制系統來數據,請參閱d6tpipe,DVC和Git大文件存儲。app

5.編寫函數而不是DAGs

聊完數據相關的內容後,讓咱們來談談實際的代碼部分!因爲您在學習編碼時學到的第一件事就是函數,所以數據科學代碼主要被組織爲一系列線性運行的函數。模塊化

1def process_data(data,parameter):
2    data = do_stuff(data)
3    data.to_pickle('data.pkl')
4data = pd.read_csv('data.csv')
5process_data(data)
6df_train = pd.read_pickle(df_train)
7model = sklearn.svm.SVC()
8model.fit(df_train.iloc [:,:-  1],df_train [ 'Y'])

解決方案:數據科學代碼不是線性地連接函數,而是更好地編寫爲一組具備它們之間依賴關係的任務。

6.寫入循環

與函數同樣,for循環是學習編碼時學到的第一件事。這個東西不難理解,但它們很慢並且過於冗長,若是你使用他們,一般就代表你並無發現矢量化的替代方案。

1x = range(10)
 2avg = sum(x)/len(x); std = math.sqrt(sum((i-avg)**2 for i in x)/len(x));
 3zscore = [(i-avg)/std for x]
 4# should be: scipy.stats.zscore(x)
 5# or
 6groupavg = []
 7for i in df['g'].unique():
 8    dfg = df[df[g']==i]
 9    groupavg.append(dfg['g'].mean())
10# should be: df.groupby('g').mean()

解決方案:Numpy,Scipy和Pandas爲您認爲可能須要循環的大多數狀況提供了矢量化函數,可隨時進去拽去您須要的。

7.忘寫單元測試

隨着數據、參數或用戶輸入的變化,您的代碼極有可能在根本沒注意到時就出現輸出錯誤的狀況。若是有人根據您的輸出結果作出決定,那麼錯誤的數據將有可能致使錯誤的決策!

解決方案:使用Assert語句檢查數據質量。Pandas也有相同的測試,d6tstack檢查數據攝取和數據鏈接。數據檢查代碼示例以下:

1assert df['id'].unique().shape[0] == len(ids) # have data for all ids?
2assert df.isna().sum()<0.9 # catch missing values
3assert df.groupby(['g','date']).size().max() ==1 # no duplicate values/date?
4assert d6tjoin.utils.PreJoin([df1,df2],['id','date']).is_all_matched() # all ids matched?

8.沒有記錄代碼

我能明白,你急着要作一些分析。因而,你把全部的數據、代碼都放在一塊兒,而後得出告終果交給你的客戶或老闆。一個星期後,他們回來講「你能改一下xyz」或「你能更新這部份內容嗎?」。而後你看着你的代碼,徹底不記得你爲何這麼作以及你怎麼去作的了。你還敢想象其餘人必須運行它這件事嗎?

1def some_complicated_function(data):
2    data = data[data['column']!='wrong']
3    data = data.groupby('date').apply(lambda x: complicated_stuff(x))
4    data = data[data['value']<0.9]
5    return data

解決方案:即便在您提供分析結果以後,也請必定要花費一部分額外的時間來記錄您的操做過程。老闆、客戶以及你本身都必定會感謝本身這麼作了!同時,這會讓你看起來更專業!

9.將數據保存爲CSV或Pickle

畢竟咱們聊的是數據科學,所以讓咱們再回到」數據「層面來看看。就像函數和for循環同樣,CSV和Pickle文件是經常使用的,但它們實際上並非最佳選擇。CSV不包含架構,所以每一個人都必須再次解析數字和日期。Pickles雖然解決了這個問題但只能在Python中使用而且沒辦法被壓縮。二者都不是存儲大型數據集的好地方。

1def process_data(data,parameter):
2    data = do_stuff(data)
3    data.to_pickle('data.pkl')
4data = pd.read_csv('data.csv')
5process_data(data)
6df_train = pd.read_pickle(df_train)

解決方案:使用parquet或其餘二進制數據格式,理論上是能夠進行數據壓縮的。d6tflow自動將任務的數據輸出保存爲parquet格式,所以您無需再對它進行處理。

10.使用Jupyter Notebooks

這裏有一個富有爭議的論點:Jupyter Notebooks和CSV同樣廣泛,有不少人都在使用它們。但這其實並不能證實他們是好用的。Jupyter Notebooks讓不少人都養成了上面所提到的不一些良編程習慣,特別是:

  • 您很想將全部文件轉儲到一個目錄中
  • 您編寫的代碼是按照top-bottom模式運行,而不是有向無環圖(DAG)模式
  • 您沒有模塊化您的代碼
  • 不易調試
  • 代碼和輸出結果混在同一個文件中
  • 缺少很好的版本控制
  • 很容易上手,但缺少較好的擴展性

解決方案: 使用 pycharm/spyder.


END

微信掃一掃
關注京東雲開發者社區公衆號,瞭解更多行業信息

圖片描述

相關文章
相關標籤/搜索