欧美三区_成人在线免费观看视频_欧美极品少妇xxxxⅹ免费视频_a级毛片免费播放_鲁一鲁中文字幕久久_亚洲一级特黄

python使用pandas處理大數據節省內存技巧(推薦)

系統 1613 0

一般來說,用pandas處理小于100兆的數據,性能不是問題。當用pandas來處理100兆至幾個G的數據時,將會比較耗時,同時會導致程序因內存不足而運行失敗。

當然,像Spark這類的工具能夠勝任處理100G至幾個T的大數據集,但要想充分發揮這些工具的優勢,通常需要比較貴的硬件設備。而且,這些工具不像pandas那樣具有豐富的進行高質量數據清洗、探索和分析的特性。對于中等規模的數據,我們的愿望是盡量讓pandas繼續發揮其優勢,而不是換用其他工具。

本文我們討論pandas的內存使用,展示怎樣簡單地為數據列選擇合適的數據類型,就能夠減少dataframe近90%的內存占用。

處理棒球比賽記錄數據

我們將處理130年的棒球甲級聯賽的數據,數據源于

python使用pandas處理大數據節省內存技巧(推薦)_第1張圖片

Retrosheet(http://www.retrosheet.org/gamelogs/index.html)

原始數據放在127個csv文件中,我們已經用csvkit

python使用pandas處理大數據節省內存技巧(推薦)_第2張圖片

(https://csvkit.readthedocs.io/en/1.0.2/)

python使用pandas處理大數據節省內存技巧(推薦)_第3張圖片

(https://data.world/dataquest/mlb-game-logs)

我們從導入數據,并輸出前5行開始:

python使用pandas處理大數據節省內存技巧(推薦)_第4張圖片

我們將一些重要的字段列在下面:

date- 比賽日期

v_name- 客隊名

v_league- 客隊聯賽

h_name- 主隊名

h_league- 主隊聯賽

v_score- 客隊得分

h_score- 主隊得分

v_line_score- 客隊線得分, 如010000(10)00.

h_line_score- 主隊線得分, 如010000(10)0X.

park_id- 主辦場地的ID

attendance- 比賽出席人數

我們可以用Dataframe.info()方法來獲得我們dataframe的一些高level信息,譬如數據量、數據類型和內存使用量。

這個方法默認情況下返回一個近似的內存使用量,現在我們設置參數memory_usage為‘deep'來獲得準確的內存使用量:

python使用pandas處理大數據節省內存技巧(推薦)_第5張圖片

我們可以看到它有171907行和161列。pandas已經為我們自動檢測了數據類型,其中包括83列數值型數據和78列對象型數據。對象型數據列用于字符串或包含混合數據類型的列。

由此我們可以進一步了解我們應該如何減少內存占用,下面我們來看一看pandas如何在內存中存儲數據。

Dataframe對象的內部表示

在底層,pandas會按照數據類型將列分組形成數據塊(blocks)。下圖所示為pandas如何存儲我們數據表的前十二列:

python使用pandas處理大數據節省內存技巧(推薦)_第6張圖片

可以注意到,這些數據塊沒有保持對列名的引用,這是由于為了存儲dataframe中的真實數據,這些數據塊都經過了優化。有個BlockManager類

python使用pandas處理大數據節省內存技巧(推薦)_第7張圖片

會用于保持行列索引與真實數據塊的映射關系。他扮演一個API,提供對底層數據的訪問。每當我們查詢、編輯或刪除數據時,dataframe類會利用BlockManager類接口將我們的請求轉換為函數和方法的調用。

每種數據類型在pandas.core.internals模塊中都有一個特定的類。pandas使用ObjectBlock類來表示包含字符串列的數據塊,用FloatBlock類來表示包含浮點型列的數據塊。對于包含數值型數據(比如整型和浮點型)的數據塊,pandas會合并這些列,并把它們存儲為一個Numpy數組(ndarray)。Numpy數組是在C數組的基礎上創建的,其值在內存中是連續存儲的。基于這種存儲機制,對其切片的訪問是相當快的。

由于不同類型的數據是分開存放的,我們將檢查不同數據類型的內存使用情況,我們先看看各數據類型的平均內存使用量:

由于不同類型的數據是分開存放的,我們將檢查不同數據類型的內存使用情況,我們先看看各數據類型的平均內存使用量:

python使用pandas處理大數據節省內存技巧(推薦)_第8張圖片

我們可以看到內存使用最多的是78個object列,我們待會再來看它們,我們先來看看我們能否提高數值型列的內存使用效率。

選理解子類(Subtypes)

剛才我們提到,pandas在底層將數值型數據表示成Numpy數組,并在內存中連續存儲。這種存儲方式消耗較少的空間,并允許我們較快速地訪問數據。由于pandas使用相同數量的字節來表示同一類型的每一個值,并且numpy數組存儲了這些值的數量,所以pandas能夠快速準確地返回數值型列所消耗的字節量。

pandas中的許多數據類型具有多個子類型,它們可以使用較少的字節去表示不同數據,比如,float型就有float16、float32和float64這些子類型。這些類型名稱的數字部分表明了這種類型使用了多少比特來表示數據,比如剛才列出的子類型分別使用了2、4、8個字節。下面這張表列出了pandas中常用類型的子類型:

python使用pandas處理大數據節省內存技巧(推薦)_第9張圖片

一個int8類型的數據使用1個字節(8位比特)存儲一個值,可以表示256(2^8)個二進制數值。這意味著我們可以用這種子類型去表示從-128到127(包括0)的數值。

我們可以用numpy.iinfo類來確認每一個整型子類型的最小和最大值,如下:

python使用pandas處理大數據節省內存技巧(推薦)_第10張圖片

python使用pandas處理大數據節省內存技巧(推薦)_第11張圖片

這里我們還可以看到uint(無符號整型)和int(有符號整型)的區別。兩者都占用相同的內存存儲量,但無符號整型由于只存正數,所以可以更高效的存儲只含正數的列。

用子類型優化數值型列

我們可以用函數pd.to_numeric()來對數值型進行向下類型轉換。我們用DataFrame.select_dtypes來只選擇整型列,然后我們優化這種類型,并比較內存使用量。

python使用pandas處理大數據節省內存技巧(推薦)_第12張圖片

我們看到內存用量從7.9兆下降到1.5兆,降幅達80%。這對我們原始dataframe的影響有限,這是由于它只包含很少的整型列。

同理,我們再對浮點型列進行相應處理:

python使用pandas處理大數據節省內存技巧(推薦)_第13張圖片

我們可以看到所有的浮點型列都從float64轉換為float32,內存用量減少50%。

我們再創建一個原始dataframe的副本,將其數值列賦值為優化后的類型,再看看內存用量的整體優化效果。

python使用pandas處理大數據節省內存技巧(推薦)_第14張圖片

可以看到通過我們顯著縮減數值型列的內存用量,我們的dataframe的整體內存用量減少了7%。余下的大部分優化將針對object類型進行。

在這之前,我們先來研究下與數值型相比,pandas如何存儲字符串。

選對比數值與字符的儲存

object類型用來表示用到了Python字符串對象的值,有一部分原因是Numpy缺少對缺失字符串值的支持。因為Python是一種高層、解析型語言,它沒有提供很好的對內存中數據如何存儲的細粒度控制。

這一限制導致了字符串以一種碎片化方式進行存儲,消耗更多的內存,并且訪問速度低下。在object列中的每一個元素實際上都是存放內存中真實數據位置的指針。

下圖對比展示了數值型數據怎樣以Numpy數據類型存儲,和字符串怎樣以Python內置類型進行存儲的。

python使用pandas處理大數據節省內存技巧(推薦)_第15張圖片

圖示來源并改編自Why Python Is Slow

你可能注意到上文表中提到object類型數據使用可變(variable)大小的內存。由于一個指針占用1字節,因此每一個字符串占用的內存量與它在Python中單獨存儲所占用的內存量相等。我們用sys.getsizeof()來證明這一點,先來看看在Python單獨存儲字符串,再來看看使用pandas的series的情況。

python使用pandas處理大數據節省內存技巧(推薦)_第16張圖片

python使用pandas處理大數據節省內存技巧(推薦)_第17張圖片

你可以看到這些字符串的大小在pandas的series中與在Python的單獨字符串中是一樣的。

選用類別(categoricalas)類型優化object類型

Pandas在0.15版本中引入類別類型。category類型在底層使用整型數值來表示該列的值,而不是用原值。Pandas用一個字典來構建這些整型數據到原數據的映射關系。當一列只包含有限種值時,這種設計是很不錯的。當我們把一列轉換成category類型時,pandas會用一種最省空間的int子類型去表示這一列中所有的唯一值。

python使用pandas處理大數據節省內存技巧(推薦)_第18張圖片

為了介紹我們何處會用到這種類型去減少內存消耗,讓我們來看看我們數據中每一個object類型列中的唯一值個數。

python使用pandas處理大數據節省內存技巧(推薦)_第19張圖片

可以看到在我們包含了近172000場比賽的數據集中,很多列只包含了少數幾個唯一值。

我們先選擇其中一個object列,開看看將其轉換成類別類型會發生什么。這里我們選用第二列:day_of_week。

我們從上表中可以看到,它只包含了7個唯一值。我們用.astype()方法將其轉換為類別類型。

python使用pandas處理大數據節省內存技巧(推薦)_第20張圖片

可以看到,雖然列的類型改變了,但數據看上去好像沒什么變化。我們來看看底層發生了什么。

下面的代碼中,我們用Series.cat.codes屬性來返回category類型用以表示每個值的整型數字。

python使用pandas處理大數據節省內存技巧(推薦)_第21張圖片

可以看到,每一個值都被賦值為一個整數,而且這一列在底層是int8類型。這一列沒有任何缺失數據,但是如果有,category子類型會將缺失數據設為-1。

最后,我們來看看這一列在轉換為category類型前后的內存使用量。

存用量從9.8兆降到0.16兆,近乎98%的降幅!注意這一特殊列可能代表了我們一個極好的例子――一個包含近172000個數據的列只有7個唯一值。

這樣的話,我們把所有這種類型的列都轉換成類別類型應該會很不錯,但這里面也要權衡利弊。首要問題是轉變為類別類型會喪失數值計算能力,在將類別類型轉換成真實的數值類型前,我們不能對category列做算術運算,也不能使用諸如Series.min()和Series.max()等方法。

對于唯一值數量少于50%的object列,我們應該堅持首先使用category類型。如果某一列全都是唯一值,category類型將會占用更多內存。這是因為這樣做不僅要存儲全部的原始字符串數據,還要存儲整型類別標識。有關category類型的更多限制,參看pandas文檔。

下面我們寫一個循環,對每一個object列進行迭代,檢查其唯一值是否少于50%,如果是,則轉換成類別類型。

python使用pandas處理大數據節省內存技巧(推薦)_第22張圖片

更之前一樣進行比較:

python使用pandas處理大數據節省內存技巧(推薦)_第23張圖片

這本例中,所有的object列都被轉換成了category類型,但其他數據集就不一定了,所以你最好還是得使用剛才的檢查過程。

本例的亮點是內存用量從752.72兆降為51.667兆,降幅達93%。我們將其與我們dataframe的剩下部分合并,看看初始的861兆數據降到了多少。

耶,看來我們的進展還不錯!我們還有一招可以做優化,如果你記得我們剛才那張類型表,會發現我們數據集第一列還可以用datetime類型來表示。

python使用pandas處理大數據節省內存技巧(推薦)_第24張圖片

你可能還記得這一列之前是作為整型讀入的,并優化成了uint32。因此,將其轉換成datetime會占用原來兩倍的內存,因為datetime類型是64位比特的。將其轉換為datetime的意義在于它可以便于我們進行時間序列分析。

轉換使用pandas.to_datetime()函數,并使用format參數告之日期數據存儲為YYYY-MM-DD格式。

python使用pandas處理大數據節省內存技巧(推薦)_第25張圖片

在數據讀入的時候設定數據類型

目前為止,我們探索了一些方法,用來減少現有dataframe的內存占用。通過首先讀入dataframe,再對其一步步進行內存優化,我們可以更好地了解這些優化方法能節省多少內存。然而,正如我們之前談到,我們通常沒有足夠的內存去表達數據集中的所有數據。如果不能在一開始就創建dataframe,我們怎樣才能應用內存節省技術呢?

幸運的是,我們可以在讀入數據集的時候指定列的最優數據類型。pandas.read_csv()函數有一些參數可以做到這一點。dtype參數接受一個以列名(string型)為鍵字典、以Numpy類型對象為值的字典。

首先,我們將每一列的目標類型存儲在以列名為鍵的字典中,開始前先刪除日期列,因為它需要分開單獨處理。

python使用pandas處理大數據節省內存技巧(推薦)_第26張圖片

現在我們使用這個字典,同時傳入一些處理日期的參數,讓日期以正確的格式讀入。

python使用pandas處理大數據節省內存技巧(推薦)_第27張圖片

python使用pandas處理大數據節省內存技巧(推薦)_第28張圖片

通過對列的優化,我們是pandas的內存用量從861.6兆降到104.28兆,有效降低88%。

分析棒球比賽

現在我們有了優化后的數據,可以進行一些分析。我們先看看比賽日的分布情況。

python使用pandas處理大數據節省內存技巧(推薦)_第29張圖片

python使用pandas處理大數據節省內存技巧(推薦)_第30張圖片

我們可以看到,1920年代之前,周日棒球賽很少是在周日的,隨后半個世紀才逐漸增多。

我們也看到最后50年的比賽日分布變化相對比較平穩。

我們來看看比賽時長的逐年變化。

python使用pandas處理大數據節省內存技巧(推薦)_第31張圖片

看來棒球比賽時長從1940年代之后逐漸變長。

總結

我們學習了pandas如何存儲不同的數據類型,并利用學到的知識將我們的pandas dataframe的內存用量降低了近90%,僅僅只用了一點簡單的技巧:

將數值型列降級到更高效的類型

將字符串列轉換為類別類型

通過對列的優化,我們是pandas的內存用量從861.6兆降到104.28兆,有效降低88%。

以上所述是小編給大家介紹的python使用pandas處理大數據節省內存技巧詳解整合,希望對大家有所幫助,如果大家有任何疑問請給我留言,小編會及時回復大家的。在此也非常感謝大家對腳本之家網站的支持!


更多文章、技術交流、商務合作、聯系博主

微信掃碼或搜索:z360901061

微信掃一掃加我為好友

QQ號聯系: 360901061

您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點擊下面給點支持吧,站長非常感激您!手機微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點擊微信右上角掃一掃功能,選擇支付二維碼完成支付。

【本文對您有幫助就好】

您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描上面二維碼支持博主2元、5元、10元、自定義金額等您想捐的金額吧,站長會非常 感謝您的哦!!!

發表我的評論
最新評論 總共0條評論
主站蜘蛛池模板: 日韩一区二区在线视频 | yy4138理论片在线大全 | 国产精品岛国久久久久久 | 亚洲精品成人 | 国产精品久久久久久久久免费相片 | 91精品欧美成人 | 激情网址在线观看 | 日本视频在线免费观看 | 波多野结衣99 | 国产一区二| 欧美一区二区视频 | 欧美一级毛片在线 | 波多野一区 | 国产精品日本欧美一区二区 | 免费在线观看视频a | 日韩一区二区在线视频 | 亚洲激情视频在线观看 | 日本一区二区三区四区 | 久久综合九色综合欧美播 | 欧美在线播放一区 | 人人人人干 | 日韩在线观看视频一区 | 久久久一区二区三区精品 | 欧美日韩国产一区二区三区 | 亚洲资源在线 | 国产日韩视频 | 免费看一级欧美毛片视频 | 日韩久久久久久 | 俄罗斯厕所偷窥视频 | 夜夜操夜夜骑 | 羞羞电影在线观看 | 亚洲一区二区三区首页 | 精品国产影院 | 中文欧美日韩 | 在线视频 中文字幕 | 精品国内视频 | 一区二区三区四区在线 | 欧美精品1区 | 一级视频片 | 一区二区不卡在线观看 | 一本大道久久a久久精二百 日韩三级中文 |