首頁 > 軟體

Python資料集庫Vaex秒開100GB加資料

2022-06-13 18:01:51

前言

如果你50GB甚至500GB的資料集,開啟他們都很困難了,更別說分析了。

在處理這樣的資料集時,我們通常採用3種方法。

第一種對資料進抽樣:這裡的缺點是顯而易見的,樣本資料能否代表整個資料。

第二種使用分散式計算:雖然在某些情況下這是一種有效的方法,但是它帶來了管理和維護叢集的巨大開銷。想象一下,必須為一個剛好超出RAM範圍的資料集設定一個叢集,比如在30-50GB範圍內。這有點過分了。

第三種租用一個強大的雲服務:例如,AWS提供了具有TB記憶體的範例。在這種情況下,你仍然需要管理雲資料,每次啟動時都要等待一個個的資料傳輸。處理將資料放到雲上所帶來的遵從性問題,以及處理在遠端機器上工作所帶來的所有不便。更不用說成本了,儘管開始時成本很低,但隨著時間的推移,成本往往會越來越高。

在本文中,我們將向你展示一種新的方法:一種更快、更安全、總體上更方便的方法,可以使用幾乎任意大小的資料進行資料研究分析,只要它能夠適用於筆記型電腦、桌上型電腦或伺服器的硬碟機。

Vaex

Vaex是一個開源的DataFrame庫,它可以對錶格資料集進行視覺化、探索、分析,甚至機器學習,這些資料集和你的硬碟機一樣大。它可以在一個n維網格上每秒計算超過10億(10^9)個物件的平均值、和、計數、標準差等統計資訊。視覺化使用直方圖、使用直方圖、密度圖和3D立體渲染進行視覺化。為此,Vaex採用了記憶體對映、高效的外核演演算法和延遲計算等概念來獲得最佳效能(不浪費記憶體)。所有這些都封裝在一個類似Pandas的API中。

GitHub:https://github.com/vaexio/vaex

為了說明Vaex的效能,我們為大家舉個例子。

資料準備

我們使用紐約市計程車的資料集,該資料集包含了計程車在2009年至2015年間超過10億次計程車出行的資訊。資料可從下面的網站下載,並以 CSV 格式提供:

https://www1.nyc.gov/site/tlc/about/tlc-trip-record-data.page

資料淨化

第一步將資料轉換為記憶體對映檔案格式,如Apache Arrow、Apache Parque 或HDF5。一旦資料成為記憶體對映格式,使用Vaex開啟它是瞬間的(資料的磁碟大小超過100GB)。有多塊?

0.052秒!

將CSV資料轉換為HDF5的程式碼如下:

為什麼這麼快?

當你使用Vaex開啟記憶體對映檔案時,實際上沒有資料讀取。Vaex唯讀取檔案後設資料,比如磁碟上資料的位置、資料結構(行數、列數、列名和型別)、檔案描述等等。那麼,如果我們想要檢查或與資料互動呢?開啟一個資料集會得到一個標準的DataFrame:

再次注意,單元執行時間非常短。這是因為顯示Vaex DataFrame或列只需要從磁碟讀取前5行和後5行。這就引出了另一個重要的問題:Vaex只會在必要時遍歷整個資料集,而且它會盡可能少地遍歷資料。

現在開始清理資料集。一個好的開始方法是使用describe方法獲得資料的概覽:

describe方法很好地說明了Vaex的效能和效率:所有這些統計資料都是在MacBook Pro(15英寸,2018年,2.6GHz Intel Core i7,32GB RAM)上用不到3分鐘計算出來的。其他庫或方法需要分散式計算或超過100GB的雲才能預先相同的計算。有了Vaex,你所需要的只是資料,以及只有幾GB記憶體的筆記型電腦。

檢視description的輸出,很容易注意到資料包含一些嚴重的異常值。由於我們使用的是如此龐大的資料集,直方圖是最有效的視覺化方法。用Vaex建立和顯示柱狀圖和熱圖是如此的快,這樣的圖可又是互動式的!

df.plot_widget(df.pickup_longitude,
               df.pickup_latitude,
               shape=512,
               limits='minmax',
               f='log1p',
               colormap='plasma')

一旦我們決定了想要關注紐約的哪個區域,我們就可以簡單地建立一個過濾後的 DataFrame:

上面的程式碼塊的優點在於:它所需要的記憶體可以忽略不計!在過濾Vaex DataFrame時,不會生成資料副本。相反,只建立對原始物件的參照,並在其上應用二進位制掩碼。掩碼選擇顯示哪些行並用於將來的計算。這為我們節省了100GB的RAM,如果要複製資料,就需要這樣做,就像現在許多標準的資料分析所做的那樣。

現在,讓我們檢查一下passenger_count列。單次乘坐計程車的最高記錄是255人,這似乎有點極端。讓我們數一數每一名乘客的出行次數。使用value_counts方法很容易做到這一點:

應用10億行的“value_counts”方法只需要20秒!

從上圖中我們可以看出,乘客超過6人的出行很可能是罕見的異常值,或者是資料輸入錯誤。也有大量的出現,沒有(0名)乘客。既然現在我們還不知道這些旅行是否合法,那就讓我們把它們過濾掉吧。

讓我們做一個關於類似出行距離的操作。由於這是一個連續的變數,我們可以畫出出行距離的分佈。看看最小和最大的距離,讓我們用一個更合理的範圍來繪製直方圖。

從上圖中我們可以看到,出行次數隨著距離的增加而減少。在大約100英里的距離上,分佈有很大的下降。現在,我們用這個作為分界點,來消除基於行程距離的極端異常值:

出行距離列中存在的極端離群值是調查出租車出行時間和平均速度的原因。這些特徵在資料集中是不容易獲得的,但是計算起來很簡單:

上面的程式碼塊需要零記憶體,不需要執行時間!這是因為程式碼會建立虛擬列。這些列只包含數學表示式,僅在需要時才計算它們。否則,虛列的行為與任何其他常規列一樣。注意,其他標準庫需要10s的GB記憶體來完成相同的操作。

讓我們畫出行程時間的分佈圖:

從上圖我們可以看到,95% 的計程車行程花費不到30分鐘到達目的地,儘管有些行程花費了4-5個小時。你能想象在紐約被困在計程車裡超過3個小時的情景嗎?考慮所有總共不超過3小時的行程:

現在讓我們看一下出租車的平均速度,同時為資料限制選擇一個合理的範圍:

根據分佈趨平的地方,我們可以推斷出合理的計程車平均速度在每小時1到60英里之間,因此我們可以更新過濾後的dataframe:

讓我們把焦點轉移到計程車的費用上。從describe方法的輸出中,我們可以看到在fare_amount、total_amount和tip_amount列中存在一些異常值。對於初學者來說,這些列中的任何值都不應該是負值。讓我們看看這些資料的分佈在一個相對合理的範圍內:

我們看到上面的三個分佈都有相當長的尾部。尾部的一些值可能是正確的,而其他值可能是錯誤的資料輸入。無論如何,讓我們現在保守一點,只考慮票價為fare_amount、total_amount和tip_amount低於200美元的乘客。我們還要求fare_amount、total_amount的值大於0。

最後,在所有初始資料清理之後,讓我們看看還剩下多少出租車次數供我們分析:

超過11億次的出行! 

具體分析

假設我們使用這個資料集來學習如何最大化利潤,最小化成本。

讓我們從找出從平均值而言,能帶來較好收入的載客地點開始。我們只需繪製一張熱點地區接送地點的熱圖,對平均票價進行顏色編碼,然後檢視熱點地區。然而,計程車司機也有自己的成本。例如,燃料費用。因此,把乘客帶到很遠的地方可能會導致更高的票價,但這也意味著更大的燃料消耗和時間損失。此外,從偏遠的地方載一個乘客去市中心可能不那麼容易,因此在沒有乘客的情況下開車回去可能會很貴。一種解釋的方法是,用票價金額與出行距離之比的平均值來表示熱圖的顏色。讓我們考慮一下這兩種方法:

計程車司機是一份相當靈活的工作。除了知道應該去哪裡,如果讓他們知道什麼時候開車最賺錢也是很有用的。為了回答這個問題,讓我們製作一個圖表,顯示每天和每小時的平均票價與行程的比率:

上面的數位是合理的,最好的收入發生在高峰時間,特別是中午,在工作日。作為一名計程車司機,我們收入的一部分給了計程車公司,所以我們可能會對哪一天、哪段時間顧客給的小費最多感興趣。讓我們製作一個類似的圖,這次顯示的是平均小費的比例:

上面的結論很有趣。它告訴我們,乘客在早上7點到10點之間給出租車司機的小費最多,如果你在凌晨3點或4點接乘客,不要指望會有大額小費。

更深入的分析

在本文的前一部分中,我們簡要地集中討論了trip_distance列,在去除異常值時,我們保留了所有值小於100英里的行程。但這仍然是一個相當大的臨界值,尤其是考慮到Yellow Taxi公司主要在曼哈頓運營。trip_distance列描述計程車從上客點到下客點的距離。然而,人們經常可以選擇不同的路線,在兩個確切的上落地點之間有不同的距離,例如為了避免交通堵塞或道路工程。因此,作為trip_distance列的一個對應項,讓我們計算接送位置之間可能的最短距離,我們稱之為arc_distance:

對於用Numpy編寫的複雜表示式,vaex可以在Numba、Pythran甚至CUDA(如果你有NVIDIA GPU的話)的幫助下使用即時編譯來極大地提高你的計算速度。

arc_distance的計算公式非常複雜,它包含了大量的三角函數和算術知識,特別是在處理巨量資料集的情況下,計算量很大。如果表示式或函數僅使用來自Numpy包的Python操作和方法編寫,Vaex將使用計算機的所有核心並行地計算它。除此之外,Vaex通過Numba(使用LLVM)或Pythran(通過C++加速)支援即時編譯,從而提供更好的效能。如果你有NVIDIA顯示卡,你可以通過jit_cuda方法使用CUDA來獲得更快的效能。

無論如何,我們來畫一下trip_distance和arc_distance的分佈:

有趣的是,arc_distance從未超過21英里,但計程車實際行駛的距離可能是它的5倍。事實上,在數百萬次的計程車行程中,落客點距離接客點只有100米(0.06英里)。

我們這次試用的資料集跨越了7年。我們可以看看在這段時間裡,人們對某些東西的興趣是如何演變的,可能會很有趣。使用Vaex,我們可以進行out-of-core group-by和aggregation操作。讓我們來看看這7年中票價和旅行距離的變化:

在擁有四核處理器的筆記型電腦上,對一個擁有超過10億個樣本的Vaex DataFrame進行8個聚合的分組操作只需不到2分鐘。

在上面的單元格格中,我們執行groupby操作,然後執行8個聚合,其中2個位於虛擬列上。上面的單元格在我們的筆記型電腦上執行不到2分鐘。考慮到我們使用的資料包含超過10億個樣本,這是相當令人印象深刻的。不管怎樣,讓我們看看結果。以下是多年來乘坐計程車的費用是如何演變的:

我們看到,隨著時間的流逝,計程車費和小費都在上漲。現在讓我們看看出租車的trip_distance 和arc_distance作為年的函數:

上圖顯示,trip_distance和arc_distance都有一個小的增長,這意味著,平均而言,人們傾向於每年走得更遠一點。

讓我們再調查一下乘客是如何支付他們的車費的:payment_type列,讓我們看看它包含的值:

從資料集中,我們可以看到只有6個有效的條目:

  • 1=信用卡支付
  • 2=現金支付
  • 3=不收費
  • 4=糾紛
  • 5=未知
  • 6=無效行程

因此,我們可以簡單地將payment_type列中的條目對映到整數:

現在我們可以根據每年的資料進行分組,看看紐約人在支付打車費用方面的習慣是如何改變的:

我們發現,隨著時間的推移,信用卡支付慢慢變得比現金支付更頻繁。在上面的程式碼塊中,一旦我們聚合了資料,小型的Vaex dataframe就可以很容易地轉換為Pandas DataFrame,將其傳遞給Seaborn。

最後,讓我們通過繪製現金支付與信用卡支付之間的比率來檢視付款方法是否取決於當天的時間或星期幾。為此,我們將首先建立一個過濾器,它只選擇用現金或信用卡支付。下一步是具有Vaex特色功能的操作:帶有選擇的聚合。其他庫要求對每個支付方法進行聚合,然後將這些支付方法後來合併為一個支付方法。 另一方面,我們可以通過在聚合函數中提供的引數,一步完成這個操作。 這非常方便,只需要傳遞一次資料,就可以獲得更好的效能。 然後,我們可以用標準的方式繪製出最終的DataFrame:

從上面的圖可以看出,顯示的小費百分比可以作為一週的某天或一天的某時段的函數。從這兩個圖中表明,用信用卡支付的乘客比用現金支付的乘客更傾向於給小費。看看分佈:

乘客多久付一次小費?

但是讓我們看看_fareamount和_totalamount的分佈,這取決於支付方式是刷卡還是現金。

結論

有了Vaex,你可以在短短几秒鐘內瀏覽超過10億行資料,計算各種統計資料、聚合資訊,並生成資訊圖表,而這一切都是在你自己的筆記型電腦上完成的。而且它是免費和開源的!

以上就是Python資料集庫Vaex秒開100GB加資料的詳細內容,更多關於Python庫Vaex秒開100GB資料的資料請關注it145.com其它相關文章!


IT145.com E-mail:sddin#qq.com