python如何使用pandas處理大數(shù)據(jù)節(jié)省內(nèi)存-創(chuàng)新互聯(lián)

小編給大家分享一下python如何使用pandas處理大數(shù)據(jù)節(jié)省內(nèi)存,相信大部分人都還不怎么了解,因此分享這篇文章給大家參考一下,希望大家閱讀完這篇文章后大有收獲,下面讓我們一起去了解一下吧!

創(chuàng)新互聯(lián)公司堅(jiān)持“要么做到,要么別承諾”的工作理念,服務(wù)領(lǐng)域包括:做網(wǎng)站、成都網(wǎng)站設(shè)計(jì)、企業(yè)官網(wǎng)、英文網(wǎng)站、手機(jī)端網(wǎng)站、網(wǎng)站推廣等服務(wù),滿足客戶于互聯(lián)網(wǎng)時(shí)代的礦區(qū)網(wǎng)站設(shè)計(jì)、移動(dòng)媒體設(shè)計(jì)的需求,幫助企業(yè)找到有效的互聯(lián)網(wǎng)解決方案。努力成為您成熟可靠的網(wǎng)絡(luò)建設(shè)合作伙伴!

一般來(lái)說(shuō),用pandas處理小于100兆的數(shù)據(jù),性能不是問(wèn)題。當(dāng)用pandas來(lái)處理100兆至幾個(gè)G的數(shù)據(jù)時(shí),將會(huì)比較耗時(shí),同時(shí)會(huì)導(dǎo)致程序因內(nèi)存不足而運(yùn)行失敗。

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

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

處理棒球比賽記錄數(shù)據(jù)

我們將處理130年的棒球甲級(jí)聯(lián)賽的數(shù)據(jù),數(shù)據(jù)源于

python如何使用pandas處理大數(shù)據(jù)節(jié)省內(nèi)存

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

原始數(shù)據(jù)放在127個(gè)csv文件中,我們已經(jīng)用csvkit

python如何使用pandas處理大數(shù)據(jù)節(jié)省內(nèi)存

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

python如何使用pandas處理大數(shù)據(jù)節(jié)省內(nèi)存

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

我們從導(dǎo)入數(shù)據(jù),并輸出前5行開始:

python如何使用pandas處理大數(shù)據(jù)節(jié)省內(nèi)存

python如何使用pandas處理大數(shù)據(jù)節(jié)省內(nèi)存

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

date- 比賽日期

v_name- 客隊(duì)名

v_league- 客隊(duì)聯(lián)賽

h_name- 主隊(duì)名

h_league- 主隊(duì)聯(lián)賽

v_score- 客隊(duì)得分

h_score- 主隊(duì)得分

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

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

park_id- 主辦場(chǎng)地的ID

attendance- 比賽出席人數(shù)

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

這個(gè)方法默認(rèn)情況下返回一個(gè)近似的內(nèi)存使用量,現(xiàn)在我們?cè)O(shè)置參數(shù)memory_usage為‘deep'來(lái)獲得準(zhǔn)確的內(nèi)存使用量:

python如何使用pandas處理大數(shù)據(jù)節(jié)省內(nèi)存

我們可以看到它有171907行和161列。pandas已經(jīng)為我們自動(dòng)檢測(cè)了數(shù)據(jù)類型,其中包括83列數(shù)值型數(shù)據(jù)和78列對(duì)象型數(shù)據(jù)。對(duì)象型數(shù)據(jù)列用于字符串或包含混合數(shù)據(jù)類型的列。

由此我們可以進(jìn)一步了解我們應(yīng)該如何減少內(nèi)存占用,下面我們來(lái)看一看pandas如何在內(nèi)存中存儲(chǔ)數(shù)據(jù)。

Dataframe對(duì)象的內(nèi)部表示

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

python如何使用pandas處理大數(shù)據(jù)節(jié)省內(nèi)存

可以注意到,這些數(shù)據(jù)塊沒有保持對(duì)列名的引用,這是由于為了存儲(chǔ)dataframe中的真實(shí)數(shù)據(jù),這些數(shù)據(jù)塊都經(jīng)過(guò)了優(yōu)化。有個(gè)BlockManager類

python如何使用pandas處理大數(shù)據(jù)節(jié)省內(nèi)存

會(huì)用于保持行列索引與真實(shí)數(shù)據(jù)塊的映射關(guān)系。他扮演一個(gè)API,提供對(duì)底層數(shù)據(jù)的訪問(wèn)。每當(dāng)我們查詢、編輯或刪除數(shù)據(jù)時(shí),dataframe類會(huì)利用BlockManager類接口將我們的請(qǐng)求轉(zhuǎn)換為函數(shù)和方法的調(diào)用。

每種數(shù)據(jù)類型在pandas.core.internals模塊中都有一個(gè)特定的類。pandas使用ObjectBlock類來(lái)表示包含字符串列的數(shù)據(jù)塊,用FloatBlock類來(lái)表示包含浮點(diǎn)型列的數(shù)據(jù)塊。對(duì)于包含數(shù)值型數(shù)據(jù)(比如整型和浮點(diǎn)型)的數(shù)據(jù)塊,pandas會(huì)合并這些列,并把它們存儲(chǔ)為一個(gè)Numpy數(shù)組(ndarray)。Numpy數(shù)組是在C數(shù)組的基礎(chǔ)上創(chuàng)建的,其值在內(nèi)存中是連續(xù)存儲(chǔ)的?;谶@種存儲(chǔ)機(jī)制,對(duì)其切片的訪問(wèn)是相當(dāng)快的。

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

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

python如何使用pandas處理大數(shù)據(jù)節(jié)省內(nèi)存

我們可以看到內(nèi)存使用最多的是78個(gè)object列,我們待會(huì)再來(lái)看它們,我們先來(lái)看看我們能否提高數(shù)值型列的內(nèi)存使用效率。

選理解子類(Subtypes)

剛才我們提到,pandas在底層將數(shù)值型數(shù)據(jù)表示成Numpy數(shù)組,并在內(nèi)存中連續(xù)存儲(chǔ)。這種存儲(chǔ)方式消耗較少的空間,并允許我們較快速地訪問(wèn)數(shù)據(jù)。由于pandas使用相同數(shù)量的字節(jié)來(lái)表示同一類型的每一個(gè)值,并且numpy數(shù)組存儲(chǔ)了這些值的數(shù)量,所以pandas能夠快速準(zhǔn)確地返回?cái)?shù)值型列所消耗的字節(jié)量。

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

python如何使用pandas處理大數(shù)據(jù)節(jié)省內(nèi)存

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

我們可以用numpy.iinfo類來(lái)確認(rèn)每一個(gè)整型子類型的最小和大值,如下:

python如何使用pandas處理大數(shù)據(jù)節(jié)省內(nèi)存

python如何使用pandas處理大數(shù)據(jù)節(jié)省內(nèi)存

這里我們還可以看到uint(無(wú)符號(hào)整型)和int(有符號(hào)整型)的區(qū)別。兩者都占用相同的內(nèi)存存儲(chǔ)量,但無(wú)符號(hào)整型由于只存正數(shù),所以可以更高效的存儲(chǔ)只含正數(shù)的列。

用子類型優(yōu)化數(shù)值型列

我們可以用函數(shù)pd.to_numeric()來(lái)對(duì)數(shù)值型進(jìn)行向下類型轉(zhuǎn)換。我們用DataFrame.select_dtypes來(lái)只選擇整型列,然后我們優(yōu)化這種類型,并比較內(nèi)存使用量。

python如何使用pandas處理大數(shù)據(jù)節(jié)省內(nèi)存

我們看到內(nèi)存用量從7.9兆下降到1.5兆,降幅達(dá)80%。這對(duì)我們?cè)糳ataframe的影響有限,這是由于它只包含很少的整型列。

同理,我們?cè)賹?duì)浮點(diǎn)型列進(jìn)行相應(yīng)處理:

python如何使用pandas處理大數(shù)據(jù)節(jié)省內(nèi)存

我們可以看到所有的浮點(diǎn)型列都從float64轉(zhuǎn)換為float32,內(nèi)存用量減少50%。

我們?cè)賱?chuàng)建一個(gè)原始dataframe的副本,將其數(shù)值列賦值為優(yōu)化后的類型,再看看內(nèi)存用量的整體優(yōu)化效果。

python如何使用pandas處理大數(shù)據(jù)節(jié)省內(nèi)存

可以看到通過(guò)我們顯著縮減數(shù)值型列的內(nèi)存用量,我們的dataframe的整體內(nèi)存用量減少了7%。余下的大部分優(yōu)化將針對(duì)object類型進(jìn)行。

在這之前,我們先來(lái)研究下與數(shù)值型相比,pandas如何存儲(chǔ)字符串。

選對(duì)比數(shù)值與字符的儲(chǔ)存

object類型用來(lái)表示用到了Python字符串對(duì)象的值,有一部分原因是Numpy缺少對(duì)缺失字符串值的支持。因?yàn)镻ython是一種高層、解析型語(yǔ)言,它沒有提供很好的對(duì)內(nèi)存中數(shù)據(jù)如何存儲(chǔ)的細(xì)粒度控制。

這一限制導(dǎo)致了字符串以一種碎片化方式進(jìn)行存儲(chǔ),消耗更多的內(nèi)存,并且訪問(wèn)速度低下。在object列中的每一個(gè)元素實(shí)際上都是存放內(nèi)存中真實(shí)數(shù)據(jù)位置的指針。

下圖對(duì)比展示了數(shù)值型數(shù)據(jù)怎樣以Numpy數(shù)據(jù)類型存儲(chǔ),和字符串怎樣以Python內(nèi)置類型進(jìn)行存儲(chǔ)的。

python如何使用pandas處理大數(shù)據(jù)節(jié)省內(nèi)存

圖示來(lái)源并改編自Why Python Is Slow

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

python如何使用pandas處理大數(shù)據(jù)節(jié)省內(nèi)存

python如何使用pandas處理大數(shù)據(jù)節(jié)省內(nèi)存

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

選用類別(categoricalas)類型優(yōu)化object類型

Pandas在0.15版本中引入類別類型。category類型在底層使用整型數(shù)值來(lái)表示該列的值,而不是用原值。Pandas用一個(gè)字典來(lái)構(gòu)建這些整型數(shù)據(jù)到原數(shù)據(jù)的映射關(guān)系。當(dāng)一列只包含有限種值時(shí),這種設(shè)計(jì)是很不錯(cuò)的。當(dāng)我們把一列轉(zhuǎn)換成category類型時(shí),pandas會(huì)用一種最省空間的int子類型去表示這一列中所有的唯一值。

python如何使用pandas處理大數(shù)據(jù)節(jié)省內(nèi)存

為了介紹我們何處會(huì)用到這種類型去減少內(nèi)存消耗,讓我們來(lái)看看我們數(shù)據(jù)中每一個(gè)object類型列中的唯一值個(gè)數(shù)。

python如何使用pandas處理大數(shù)據(jù)節(jié)省內(nèi)存

可以看到在我們包含了近172000場(chǎng)比賽的數(shù)據(jù)集中,很多列只包含了少數(shù)幾個(gè)唯一值。

我們先選擇其中一個(gè)object列,開看看將其轉(zhuǎn)換成類別類型會(huì)發(fā)生什么。這里我們選用第二列:day_of_week。

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

python如何使用pandas處理大數(shù)據(jù)節(jié)省內(nèi)存

可以看到,雖然列的類型改變了,但數(shù)據(jù)看上去好像沒什么變化。我們來(lái)看看底層發(fā)生了什么。

下面的代碼中,我們用Series.cat.codes屬性來(lái)返回category類型用以表示每個(gè)值的整型數(shù)字。

python如何使用pandas處理大數(shù)據(jù)節(jié)省內(nèi)存

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

最后,我們來(lái)看看這一列在轉(zhuǎn)換為category類型前后的內(nèi)存使用量。

python如何使用pandas處理大數(shù)據(jù)節(jié)省內(nèi)存

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

這樣的話,我們把所有這種類型的列都轉(zhuǎn)換成類別類型應(yīng)該會(huì)很不錯(cuò),但這里面也要權(quán)衡利弊。首要問(wèn)題是轉(zhuǎn)變?yōu)轭悇e類型會(huì)喪失數(shù)值計(jì)算能力,在將類別類型轉(zhuǎn)換成真實(shí)的數(shù)值類型前,我們不能對(duì)category列做算術(shù)運(yùn)算,也不能使用諸如Series.min()和Series.max()等方法。

對(duì)于唯一值數(shù)量少于50%的object列,我們應(yīng)該堅(jiān)持首先使用category類型。如果某一列全都是唯一值,category類型將會(huì)占用更多內(nèi)存。這是因?yàn)檫@樣做不僅要存儲(chǔ)全部的原始字符串?dāng)?shù)據(jù),還要存儲(chǔ)整型類別標(biāo)識(shí)。有關(guān)category類型的更多限制,參看pandas文檔。

下面我們寫一個(gè)循環(huán),對(duì)每一個(gè)object列進(jìn)行迭代,檢查其唯一值是否少于50%,如果是,則轉(zhuǎn)換成類別類型。

python如何使用pandas處理大數(shù)據(jù)節(jié)省內(nèi)存

更之前一樣進(jìn)行比較:

python如何使用pandas處理大數(shù)據(jù)節(jié)省內(nèi)存

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

本例的亮點(diǎn)是內(nèi)存用量從752.72兆降為51.667兆,降幅達(dá)93%。我們將其與我們dataframe的剩下部分合并,看看初始的861兆數(shù)據(jù)降到了多少。

python如何使用pandas處理大數(shù)據(jù)節(jié)省內(nèi)存

耶,看來(lái)我們的進(jìn)展還不錯(cuò)!我們還有一招可以做優(yōu)化,如果你記得我們剛才那張類型表,會(huì)發(fā)現(xiàn)我們數(shù)據(jù)集第一列還可以用datetime類型來(lái)表示。

python如何使用pandas處理大數(shù)據(jù)節(jié)省內(nèi)存

你可能還記得這一列之前是作為整型讀入的,并優(yōu)化成了uint32。因此,將其轉(zhuǎn)換成datetime會(huì)占用原來(lái)兩倍的內(nèi)存,因?yàn)閐atetime類型是64位比特的。將其轉(zhuǎn)換為datetime的意義在于它可以便于我們進(jìn)行時(shí)間序列分析。

轉(zhuǎn)換使用pandas.to_datetime()函數(shù),并使用format參數(shù)告之日期數(shù)據(jù)存儲(chǔ)為YYYY-MM-DD格式。

python如何使用pandas處理大數(shù)據(jù)節(jié)省內(nèi)存

在數(shù)據(jù)讀入的時(shí)候設(shè)定數(shù)據(jù)類型

目前為止,我們探索了一些方法,用來(lái)減少現(xiàn)有dataframe的內(nèi)存占用。通過(guò)首先讀入dataframe,再對(duì)其一步步進(jìn)行內(nèi)存優(yōu)化,我們可以更好地了解這些優(yōu)化方法能節(jié)省多少內(nèi)存。然而,正如我們之前談到,我們通常沒有足夠的內(nèi)存去表達(dá)數(shù)據(jù)集中的所有數(shù)據(jù)。如果不能在一開始就創(chuàng)建dataframe,我們?cè)鯓硬拍軕?yīng)用內(nèi)存節(jié)省技術(shù)呢?

幸運(yùn)的是,我們可以在讀入數(shù)據(jù)集的時(shí)候指定列的最優(yōu)數(shù)據(jù)類型。pandas.read_csv()函數(shù)有一些參數(shù)可以做到這一點(diǎn)。dtype參數(shù)接受一個(gè)以列名(string型)為鍵字典、以Numpy類型對(duì)象為值的字典。

首先,我們將每一列的目標(biāo)類型存儲(chǔ)在以列名為鍵的字典中,開始前先刪除日期列,因?yàn)樗枰珠_單獨(dú)處理。

python如何使用pandas處理大數(shù)據(jù)節(jié)省內(nèi)存

現(xiàn)在我們使用這個(gè)字典,同時(shí)傳入一些處理日期的參數(shù),讓日期以正確的格式讀入。

python如何使用pandas處理大數(shù)據(jù)節(jié)省內(nèi)存

python如何使用pandas處理大數(shù)據(jù)節(jié)省內(nèi)存

通過(guò)對(duì)列的優(yōu)化,我們是pandas的內(nèi)存用量從861.6兆降到104.28兆,有效降低88%。

分析棒球比賽

現(xiàn)在我們有了優(yōu)化后的數(shù)據(jù),可以進(jìn)行一些分析。我們先看看比賽日的分布情況。

python如何使用pandas處理大數(shù)據(jù)節(jié)省內(nèi)存

python如何使用pandas處理大數(shù)據(jù)節(jié)省內(nèi)存

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

我們也看到最后50年的比賽日分布變化相對(duì)比較平穩(wěn)。

我們來(lái)看看比賽時(shí)長(zhǎng)的逐年變化。

python如何使用pandas處理大數(shù)據(jù)節(jié)省內(nèi)存

python如何使用pandas處理大數(shù)據(jù)節(jié)省內(nèi)存

看來(lái)棒球比賽時(shí)長(zhǎng)從1940年代之后逐漸變長(zhǎng)。

以上是“python如何使用pandas處理大數(shù)據(jù)節(jié)省內(nèi)存”這篇文章的所有內(nèi)容,感謝各位的閱讀!相信大家都有了一定的了解,希望分享的內(nèi)容對(duì)大家有所幫助,如果還想學(xué)習(xí)更多知識(shí),歡迎關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道!

分享文章:python如何使用pandas處理大數(shù)據(jù)節(jié)省內(nèi)存-創(chuàng)新互聯(lián)
網(wǎng)站鏈接:http://muchs.cn/article6/cshcog.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供自適應(yīng)網(wǎng)站網(wǎng)站維護(hù)、面包屑導(dǎo)航網(wǎng)站收錄、商城網(wǎng)站、虛擬主機(jī)

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來(lái)源: 創(chuàng)新互聯(lián)

外貿(mào)網(wǎng)站制作