2017-10-14 85 views
1

我已經使用Python和SciKitLearn堆棧創建了一個腳本來匹配巴西城市之間的氣候數據。目前,我正在使用帶有60M +條目的氣候集合的MongoDB,並且使用Pandas查詢並加入這些表格。如何使用Pandas和SciKitLearn Stack提高Python腳本的性能?

我用一個簡單的算法比較來自每個巴西城市的氣候數據,爲每個城市對生成一個最終得分。

問題是它需要很長時間(每對11秒)。這真的很慢,因爲我想獲得所有12M +可能組合的分數。我怎樣才能讓它更快?下面是相關代碼:

與MongoDB的(幾乎是瞬間)連接:

client = MongoClient('localhost', 27017) 
db = client.agricredit_datafetcher_development 

抓取氣候數據(快,但不是即時):從

base_weather_data = list(db.meteo_data_weather_data.find({'weather_station_id': ObjectId(base_weather_station['_id'])})) 
target_weather_data = list(db.meteo_data_weather_data.find({'weather_station_id': ObjectId(target_weather_station['_id'])})) 


return {'base_dataframe': pd.DataFrame(base_weather_data), 
     'target_dataframe': pd.DataFrame(target_weather_data)} 

獲取數據內嵌(嵌套) Mongo收藏(緩慢):

base_dataframe = dataframes['base_dataframe'].set_index('analysis_date')['weather_forecast'].apply(pd.Series) 
target_dataframe = dataframes['target_dataframe'].set_index('analysis_date')['weather_forecast'].apply(pd.Series) 

查詢刪除空值並加入D ataFrames(快,但不是即時):

available_forecast_data = base_dataframe[base_dataframe['weather_forecast'] > 0][['weather_forecast']] 
to_be_compared_data = target_dataframe[target_dataframe['weather_forecast'] > 0][['weather_forecast']] 

join_dataframe = available_forecast_data.join(to_be_compared_data, how='inner', lsuffix='_base', rsuffix='_target') 

然後我申請評分算法(這是相當快的,只是金額和平均),並然後將其插入我的蒙戈數據庫。

我該如何改進我的代碼?

這裏有幾點:

  • 我敢肯定,如果我不使用創建一個新的數據框的pd.Series方法能夠處理嵌入MongoDB的數據(第三步)。我已經試過json.normalize我的Mongo集合,然後將其轉換爲Dataframe,但速度很慢,而且當我這樣做時,一些數據會被搞亂。

  • 瓶頸在於描述的步驟。所有其他步驟(例如評分算法)都是即時的;

  • 我依靠熊貓來做查詢,分組和創建數據框。這可以嗎?我很想嘗試Mongo Aggregation Framework,看看我是否有任何改進。這值得麼?

  • Hadoop/Spark是一種改進方法嗎?我很難理解他們在數據科學項目上的角色;

編輯:第三點解決!二手蒙戈聚集而不是應用pd.Series方法對數據幀:

pipeline = [ 
    {"$match" : {"weather_station_id": ObjectId(weather_station_id)}}, 
    {"$project": { 
     'analysis_date': "$analysis_date", 
     'rainfall': "$rainfall.rainfall", 
     'agricultural_drought': "$rainfall.agricultural_drought", 
     'weather_forecast': "$weather_forecast.med_temp" 
     } 
    } 
] 

現在只需要〜1.2秒每對城市的。但我覺得我仍然可以改善這一點...現在瓶頸在weather_data查詢。但是,它被索引,有什麼辦法可以讓它更快?

編輯2:並行化我的任務與JobLibhttps://pythonhosted.org/joblib/parallel.html)縮放我的腳本虛擬速度3-4倍:)

Parallel(n_jobs=4)(delayed(insert_or_read_scores_on_db)(city['name']) for city in cities) 

還在尋找改進,雖然

+0

順便說一下,'meteo_data_weather_data',這是60M +入口數據庫被'weather_station_id'編入索引,所以我認爲在第二步中沒有辦法提高性能。 –

回答

0

我有2個這些建議可能對您有所幫助。

1)在第二步中,您正在使用適用於列的每個單元格的數據框應用函數。如果以某種方式你可以寫一個for循環來做到這一點,那麼你可以使用並行着名的python Numba庫。你可以用for循環創建一個函數,並且在這個函數中你可以給decorator @jit多核CPU中的並行工作。你需要從numba進口jit

2)我在coursera課程中看到華盛頓大學教授的一個視頻,他在那裏教他如何使用map reduce算法做兩個可以運行的表的JOIN平行。這樣,如果並行運行,您也可以快速完成Join。

+0

你的第一個陳述幫助我改進了第三點。我不知道'apply'函數一次對每個單元格都起作用。我通過使用MongoDB聚合來解決這個問題。 TY,並看到我的編輯! –