文章選自:Medium 做者:Norm Niemer 京東雲開發者社區編譯
數據科學家是「比任何軟件工程師都更擅長統計數據,比統計學家更擅長軟件工程的一批人」。許多數據科學家都有統計學背景,同時也有着一些軟件工程方面經驗。我是一名在Stackoverflow上使用Python代碼排名前1%的高級數據科學家,並與許多(初級)數據科學家們一塊兒工做。在這個過程當中,我發現你們其實都或多或少有着一些不太好的小習慣,如下是我列出的10個數據科學從業者常見的不良習慣列表。html
數據科學須要代碼和數據,這點毋庸置疑。所以,若是別人要查證到你的結果,他們就須要訪問數據。這看起來彷佛很基本,但不少人都會忘記共享他們代碼中引用數據。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
與錯誤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使您的數據易於訪問。數據庫
有人會問,因爲數據科學代碼須要數據,所以爲何不將它們轉存到同一目錄中呢?但這也意味着,當你在使用它的時候,你的圖像、報告和其餘垃圾也都會存在裏面。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點中提到的工具來存儲和共享數據。)微信
大多數人如今用版本控制系統來管理他們的代碼(若是你不這樣的話,那將會是另外一個錯誤!!🙂)。在嘗試共享數據時,可能很容易將數據文件添加到版本控制中。這對於很是小的文件是能夠的,可是git沒有針對數據進行優化,尤爲是大文件。架構
1git add data.csv
解決方案:建議使用第1點中提到的工具來存儲和共享數據。若是您真的想要版本控制系統來數據,請參閱d6tpipe,DVC和Git大文件存儲。app
聊完數據相關的內容後,讓咱們來談談實際的代碼部分!因爲您在學習編碼時學到的第一件事就是函數,所以數據科學代碼主要被組織爲一系列線性運行的函數。模塊化
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'])
解決方案:數據科學代碼不是線性地連接函數,而是更好地編寫爲一組具備它們之間依賴關係的任務。
與函數同樣,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爲您認爲可能須要循環的大多數狀況提供了矢量化函數,可隨時進去拽去您須要的。
隨着數據、參數或用戶輸入的變化,您的代碼極有可能在根本沒注意到時就出現輸出錯誤的狀況。若是有人根據您的輸出結果作出決定,那麼錯誤的數據將有可能致使錯誤的決策!
解決方案:使用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?
我能明白,你急着要作一些分析。因而,你把全部的數據、代碼都放在一塊兒,而後得出告終果交給你的客戶或老闆。一個星期後,他們回來講「你能改一下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
解決方案:即便在您提供分析結果以後,也請必定要花費一部分額外的時間來記錄您的操做過程。老闆、客戶以及你本身都必定會感謝本身這麼作了!同時,這會讓你看起來更專業!
畢竟咱們聊的是數據科學,所以讓咱們再回到」數據「層面來看看。就像函數和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格式,所以您無需再對它進行處理。
這裏有一個富有爭議的論點:Jupyter Notebooks和CSV同樣廣泛,有不少人都在使用它們。但這其實並不能證實他們是好用的。Jupyter Notebooks讓不少人都養成了上面所提到的不一些良編程習慣,特別是:
解決方案: 使用 pycharm/spyder.
微信掃一掃
關注京東雲開發者社區公衆號,瞭解更多行業信息