【譯】利用Pandas和SQLite提高超大數據的讀取速度

做者:Itamar Turner-Trauringpython

翻譯:老齊sql

與本文相關的圖書推薦:《跟老齊學Python:數據分析》數據庫


讓咱們想象,你有一個很是大的數據集,以致於讀入內存以後會致使溢出,可是你想將它的一部分用Pandas進行處理,若是你在某個時間點只是想加載這個數據集的一部分,可使用分塊方法。bash

若是把數據集分爲若干部分以後,分別加載進來,最終仍是會很慢。服務器

此時的解決方法,就是建立一個可供搜索的索引,使用SQLite就能輕鬆解決。markdown

第一個方法:分塊

來設想一個具體的示例:你要參加某個競選,爲此,你找到了一個CSV文件,裏面包含你所在城市每一個選民的信息。因而乎你派人去挨門挨戶地拜訪,邀請特定街道的全部登記選民參與投票。app

如今,Pandas的DataFrame對象中有索引,可是必需要將數據讀入內存,然而CSV文件太大了,內存沒法容納,因而,你想到,能夠只載入你關注的記錄。函數

這就是第一個方法,進行分塊。oop

import pandas as pd

def get_voters_on_street(name): 
    return pd.concat( 
       df[df["street"] == name] for df in 
       pd.read_csv("voters.csv", chunksize=1000) 
    ) 
複製代碼

以分塊的方式加載CSV文件,而且按照街道名稱進行篩選,而後將獲得記錄併爲一體。spa

雖然逐行加載,可是關注的是比較小的子集,因此須要一些開銷。好比,對於只有70k的數據集,在個人計算機上執行上面的函數,須要574ms。2018年紐約市有460萬登記選民,挨個街道查找,須要30s。

若是咱們只作一次,不要緊,若是須要反覆作,這種方法並非最佳。

建立索引對象

索引就是摘要,有這樣一種說法:若是你關心它,就能在這裏找到大量數據。在咱們的示例中,咱們想根據街道名稱建立索引,因而就能夠快速加載投票者所在的街道了。

若是你擔憂索引數據也會超出內存,那麼數據庫則能做爲保存它們的容器,例如PostgreSQL、MySQL等數據庫都能實現。哦,你不喜歡安裝和維護那些討厭的服務,好吧,SQLite應運而生了。

SQLite是一個功能齊全的關係型數據庫,它可以像其它數據庫同樣運行,可是不須要服務器。Pyhton默認就支持這種數據庫。SQLite將數據保存在獨立的文件中,你必須管理一個SQLite數據文件,而不是CSV文件了。

用SQLite存儲數據

下面演示一下如何用Pandas操做SQLite:

1. 將數據載入SQLite,並建立索引

SQLite數據庫可以保存多張數據表,首先將voters.csv文件的數據載入SQLite,並保存爲voters.sqlite文件,在這個文件中,咱們建立一個名爲voters的表。

接下來,在SQLite中建立街道的索引。

只需以下操做:

import sqlite3

# Create a new database file:
db = sqlite3.connect("voters.sqlite")

# Load the CSV in chunks:
for c in pd.read_csv("voters.csv", chunksize=1000):
    # Append all rows to a new database table, which
    # we name 'voters':
    c.to_sql("voters", db, if_exists="append")
# Add an index on the 'street' column:
db.execute("CREATE INDEX street ON voters(street)") 
db.close()
複製代碼

雖然咱們只建立單個索引,但咱們還能夠在其餘列或多個列上建立其餘索引,從而容許咱們使用這些列快速搜索數據庫。

2. 重寫查詢函數

如今,全部數據都已經載入SQLite,咱們能夠按照街道進行檢索了。

def get_voters_for_street(street_name):
    conn = sqlite3.connect("voters.sqlite")
    q = "SELECT * FROM voters WHERE street = ?"
    values = (street_name,)
    return pd.read_sql_query(q, conn, values)
複製代碼

執行上述函數,SQLite只加載與查詢匹配的行,並其經過Pandas將它們保存爲DataFrame對象。

50多倍的加速

那個CSV文件供給70,000行記錄,原來花費了574ms,如今只用了10ms。

提速50多倍,這是由於,只須要加載咱們關心的行,而不是CSV文件中的每一行。

原文連接:pythonspeed.com/articles/in…

搜索技術問答的公衆號:老齊教室

在公衆號中回覆:老齊,可查看全部文章、書籍、課程。

以爲好看,就點贊轉發

相關文章
相關標籤/搜索