自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

Pandas圖鑒:Series 和 Index

數(shù)據(jù)庫(kù) 其他數(shù)據(jù)庫(kù)
Polars是Pandas最近的轉(zhuǎn)世(用Rust編寫,因此速度更快,它不再使用NumPy的引擎,但語(yǔ)法卻非常相似,所以學(xué)習(xí) Pandas 后對(duì)學(xué)習(xí) Polars 幫助非常大。

Pandas[1]是用Python分析數(shù)據(jù)的工業(yè)標(biāo)準(zhǔn)。只需敲幾下鍵盤,就可以加載、過(guò)濾、重組和可視化數(shù)千兆字節(jié)的異質(zhì)信息。它建立在NumPy庫(kù)的基礎(chǔ)上,借用了它的許多概念和語(yǔ)法約定,所以如果你對(duì)NumPy很熟悉,你會(huì)發(fā)現(xiàn)Pandas是一個(gè)相當(dāng)熟悉的工具。即使你從未聽(tīng)說(shuō)過(guò)NumPy,Pandas也可以讓你在幾乎沒(méi)有編程背景的情況下輕松拿捏數(shù)據(jù)分析問(wèn)題。

Pandas 給 NumPy 數(shù)組帶來(lái)的兩個(gè)關(guān)鍵特性是:

  1. 異質(zhì)類型 —— 每一列都允許有自己的類型
  2. 索引 —— 提高指定列的查詢速度

事實(shí)證明,這些功能足以使Pandas成為Excel和數(shù)據(jù)庫(kù)的強(qiáng)大競(jìng)爭(zhēng)者。

Polars[2]是Pandas最近的轉(zhuǎn)世(用Rust編寫,因此速度更快,它不再使用NumPy的引擎,但語(yǔ)法卻非常相似,所以學(xué)習(xí) Pandas 后對(duì)學(xué)習(xí) Polars 幫助非常大。

Pandas 圖鑒系列文章由四個(gè)部分組成:

  • Part 1. Motivation:Pandas圖鑒(一):Pandas vs Numpy
  • Part 2. Series and Index
  • Part 3. DataFrames
  • Part 4. MultiIndex

我們將拆分成四個(gè)部分,依次呈現(xiàn)~建議關(guān)注和星標(biāo)@公眾號(hào):數(shù)據(jù)STUDIO,精彩內(nèi)容等你來(lái)~

Part 2. Series 和 Index

Series剖析Series剖析

Series是NumPy中一維數(shù)組的對(duì)應(yīng)物,是DataFrame代表其列的基本構(gòu)件。盡管與DataFrame相比,它的實(shí)際重要性正在減弱(你完全可以在不知道Series是什么的情況下解決很多實(shí)際問(wèn)題),但如果不先學(xué)習(xí)Series和Index,可能很難理解DataFrame的工作原理。

在內(nèi)部,Series將數(shù)值存儲(chǔ)在一個(gè)普通的NumPy向量中。因此,它繼承了它的優(yōu)點(diǎn)(緊湊的內(nèi)存布局,快速的隨機(jī)訪問(wèn))和缺點(diǎn)(類型同質(zhì)性,緩慢的刪除和插入)。在此基礎(chǔ)上,可以通過(guò)標(biāo)簽訪問(wèn)Series的值,使用一個(gè)叫做index的類似數(shù)字的結(jié)構(gòu)。標(biāo)簽可以是任何類型的(通常是字符串和時(shí)間戳)。它們不需要是唯一的,但唯一性是提高查詢速度所需要的,并且在許多操作中都是假定的。

圖片圖片

現(xiàn)在每個(gè)元素都可以用兩種方式來(lái)處理:通過(guò)label(=使用索引)和通過(guò)position(=不使用索引):

圖片圖片

按位置尋址by position 有時(shí)被稱為 by positional index,這只是增加了混亂。

很明顯,一對(duì)方括號(hào)是不夠的。特別是:

  • s[2:3]不是解決2號(hào)元素的最方便方式
  • 如果標(biāo)簽恰好是整數(shù),s[1:3]就變得模糊不清。它可能是指標(biāo)簽1到3(含)或位置指數(shù)1到3(不含)。

為了解決這些問(wèn)題,Pandas又有兩種方括號(hào)的 "口味":

圖片圖片

  • .loc[]總是使用標(biāo)簽并包括區(qū)間的兩端;
  • .iloc[]總是使用位置索引,并排除了右端。

在這里使用方括號(hào)而不是小括號(hào)的目的是為了獲得方便的Python切分:可以使用一個(gè)單冒號(hào)或雙冒號(hào),其含義是熟悉的start:stop:step。缺失的 start(end) 就是從系列的開(kāi)始(到結(jié)束)。步驟參數(shù)允許用s.iloc[::2]來(lái)引用偶數(shù)行,用s['Paris':'Oslo':-1]來(lái)獲取反向順序的元素。

它們還支持布爾索引(用布爾數(shù)組進(jìn)行索引),如該圖所示:

Series.isin(), Series.between()Series.isin(), Series.between()

而可以在這張圖片中看到他們是如何支持 "花式索引" 的(用整數(shù)陣列進(jìn)行索引):

圖片圖片

由于某些原因,Series沒(méi)有一個(gè)漂亮的富文本外觀,所以與DataFrame相比,看似比較低級(jí):

圖片圖片

這里對(duì)Series進(jìn)行稍加修飾,使其看起來(lái)更好,如下圖所示:

圖片圖片

豎線意味著這是一個(gè)Series,而不是一個(gè)DataFrame。

也可以用pdi.sidebyside(obj1, obj2, ...)來(lái)并排顯示幾個(gè)系列或DataFrames:

圖片圖片

pdi(代表pandas illustrated)是github上的一個(gè)開(kāi)源庫(kù)pdi[3],具有本文的這個(gè)和其他功能。安裝非常方便:

pip install pandas-illustrated

索引

負(fù)責(zé)通過(guò)標(biāo)簽獲取系列元素(以及DataFrame的行和列)的對(duì)象被稱為索引。索引速度很快:無(wú)論有5個(gè)元素還是50億個(gè)元素,都可以在一定的時(shí)間內(nèi)得到結(jié)果。

索引是一個(gè)真正的多態(tài)對(duì)象。默認(rèn)情況下,當(dāng)創(chuàng)建一個(gè)沒(méi)有索引參數(shù)的Series(或DataFrame)時(shí),它初始化為一個(gè)類似于Python的range()的惰性對(duì)象。就像range()一樣,它幾乎不使用任何內(nèi)存,并提供與位置索引相吻合的標(biāo)簽。

現(xiàn)在創(chuàng)建一個(gè)有一百萬(wàn)個(gè)元素的系列:

>>> s = pd.Series(np.zeros(10**6))
>>> s.index
RangeIndex(start=0, stop=1000000, step=1)
>>> s.index.memory_usage() # 字節(jié)數(shù)
128 # 與Series([0.])的情況相同

現(xiàn)在,如果刪除一個(gè)元素,索引就會(huì)隱含地變形為一個(gè)類似口令的結(jié)構(gòu),如下所示:

>>> s1 = s.drop(1)
>>> s1.index
Int64Index([ 0, 2, 3, 4, 5, 6, 7、
      ...
      999993, 999994, 999995, 999996, 999997, 999998, 999999],
      dtype='int64', length=999999)
>>> s1.index.memory_usage()
7999992

這個(gè)結(jié)構(gòu)消耗了8Mb的內(nèi)存!,為了避免這種情況,并回到輕量級(jí)的類似范圍的結(jié)構(gòu),我們寫下:

>>> s2 = s1.reset_index(drop=True)。
>>> s2.index
RangeIndex(start=0, stop=999999, step=1)
>>> s2.index.memory_usage()
128

如果你是Pandas的新手,你可能會(huì)想為什么Pandas不自己做呢?對(duì)于非數(shù)字標(biāo)簽來(lái)說(shuō),這有點(diǎn)顯而易見(jiàn):為什么(以及如何)Pandas在刪除一行后,會(huì)重新標(biāo)記所有后續(xù)的行?對(duì)于數(shù)字標(biāo)簽,答案就有點(diǎn)復(fù)雜了。

首先,Pandas 純粹通過(guò)位置來(lái)引用行,所以如果想在刪除第3行之后再去找第5行,可以不用重新索引(這就是iloc的作用)。

第二,保留原始標(biāo)簽是一種與過(guò)去某個(gè)時(shí)刻保持聯(lián)系的方式,就像 "保存游戲" 按鈕。如果你有一個(gè)有一百列和一百萬(wàn)行的大表,需要找到一些數(shù)據(jù)。你逐一進(jìn)行了幾次查詢,每次都縮小了搜索范圍,但只看了列的一個(gè)子集,因?yàn)橥瑫r(shí)看到所有的一百個(gè)字段是不現(xiàn)實(shí)的。現(xiàn)在你已經(jīng)找到了目標(biāo)行,想看到原始表中關(guān)于它們的所有信息。一個(gè)數(shù)字索引可以幫助你立即得到它。

從原理上講,如下圖所示:

圖片圖片

一般來(lái)說(shuō),需要保持索引值的唯一性。例如,在索引中存在重復(fù)的值時(shí),查詢速度的提升并不會(huì)提升。Pandas沒(méi)有像關(guān)系型數(shù)據(jù)庫(kù)那樣的 "唯一約束"(該功能[4]仍在試驗(yàn)中),但它有一些函數(shù)來(lái)檢查索引中的值是否唯一,并以各種方式刪除重復(fù)值。

有時(shí),但一索引不足以唯一地識(shí)別某行。例如,同名的城市有時(shí)碰巧出現(xiàn)在不同的國(guó)家,甚至在同一個(gè)國(guó)家的不同地區(qū)。因此,(城市,州)是一個(gè)比單獨(dú)的城市更適合識(shí)別一個(gè)地方的候選者。在數(shù)據(jù)庫(kù)中,它被稱為 "復(fù)合主鍵"。在Pandas中,它被稱為MultiIndex(第4部分),索引內(nèi)的每一列都被稱為level。

索引的另一個(gè)重要特性是它是不可改變的。與DataFrame中的普通列相比,你不能就地修改它。索引中的任何變化都涉及到從舊的索引中獲取數(shù)據(jù),改變它,并將新的數(shù)據(jù)作為一個(gè)新的索引重新連接起來(lái)。例如,要將列名就地轉(zhuǎn)換為字符串(節(jié)省內(nèi)存),可以寫df.columns = df.columns.astype(str),或者不就地轉(zhuǎn)換(對(duì)鏈?zhǔn)椒椒ㄓ杏茫ヾf.set_axis(df.columns.astype(str), axis=1)。但正是由于不可更改性,不允許只寫df.City.name = 'city',所以必須借助于df.rename(columns={'City': 'city'})。

索引有一個(gè)名字(在MultiIndex的情況下,每一層都有一個(gè)名字)。而這個(gè)名字在Pandas中沒(méi)有被充分使用。一旦在索引中包含了列,就不能再使用方便的df.column_name符號(hào)了,而必須恢復(fù)到不太容易閱讀的df.index或者更通用的df.loc[]。有了MultiIndex。df.merge--可以用名字指定要合并的列,不管這個(gè)列是否屬于索引。

按值查找元素

考慮以下Series對(duì)象:

圖片圖片

索引提供了一種快速而方便的方法,可以通過(guò)標(biāo)簽找到一個(gè)值。但是,通過(guò)值來(lái)尋找標(biāo)簽?zāi)兀?/p>

s.index[s.tolist().find(x)] # 對(duì)于len(s)< 1000來(lái)說(shuō)更快
s.index[np.where(s.value==x)[0][0]] # 對(duì)于 len(s) > 1000,速度更快

pdi中有一對(duì)包裝器,叫做find()和findall(),它們速度快(因?yàn)樗鼈兏鶕?jù)Series的大小自動(dòng)選擇實(shí)際的命令),而且更容易使用。

如下代碼所示:

>>> import pdi
>>> pdi.find(s, 2)
'penguin'
>>> pdi.findall(s, 4)
Index(['cat', 'dog'], dtype='object')

缺失值

Pandas使用者對(duì)缺失值特別關(guān)注。通常情況下,可以通過(guò)向read_csv提供一個(gè)標(biāo)志來(lái)接收一個(gè)帶有NaN的DataFrame。否則,可以在構(gòu)造函數(shù)或賦值運(yùn)算符中使用None(盡管對(duì)于不同的數(shù)據(jù)類型,它的實(shí)現(xiàn)方式略有不同),例如:

圖片圖片

對(duì)于NaN,可以做的第一件事是了解是否有任何NaN。從上圖可以看出,isna()產(chǎn)生一個(gè)布爾數(shù)組,而.sum()給出缺失值的總數(shù)。

現(xiàn)在你知道它們的存在,可以選擇通過(guò)刪除、用常量值填充或插值來(lái)擺脫它們,如下所示:

fillna(), dropna(), interpolate()fillna(), dropna(), interpolate()

另一方面,可以繼續(xù)使用它們。大多數(shù)Pandas函數(shù)都會(huì)忽略缺失的值:

圖片圖片

更高級(jí)的函數(shù)(median, rank, quantile等)也是如此。

算術(shù)操作是根據(jù)索引來(lái)調(diào)整的:

圖片圖片

在索引中存在非唯一值的情況下,其結(jié)果是不一致的。不要對(duì)具有非唯一索引的系列使用算術(shù)運(yùn)算。

比較

對(duì)有缺失值的數(shù)組進(jìn)行比較可能很棘手。這里有一個(gè)例子:

>>> np.all(pd.Series([1., None, 3.]) ==
      pd.Series([1., None, 3.]))
False
>>> np.all(pd.Series([1, None, 3], dtype='Int64') ==
      pd.Series([1, None, 3], dtype='Int64'))
True
>>> np.all(pd.Series(['a', None, 'c']) ==
      pd.Series(['a', None, 'c']))
False

為了正確地進(jìn)行比較,NaN需要被替換成保證在數(shù)組中缺少的東西。例如,用''、-1或∞:

>>> np.all(s1.fillna(np.inf) == s2.fillna(np.inf))  #對(duì)所有的dtypes都有效
True

或者更好的是,使用標(biāo)準(zhǔn)的NumPy或Pandas比較函數(shù):

>>> s = pd.Series([1., None, 3.])
>>> np.array_equal(s.value, s.value, equal_nan=True)
True
>>> len(s.compare(s)) == 0
True

這里,比較函數(shù)返回一個(gè)差異列表(實(shí)際上是一個(gè)DataFrame),而array_equal直接返回一個(gè)布爾值。

當(dāng)比較混合類型的DataFrame時(shí),NumPy就會(huì)出問(wèn)題(問(wèn)題#19205[5]),而Pandas做得非常好。下面是這一情況:

>>> df = pd.DataFrame({'a': [1., None, 3.], 'b': ['x', None, 'z']})
>>> np.array_equal(df.values, df.values, equal_nan=True)
TypeError
<...>
>>> len(df.compare(df)) == 0
True

添加、插入、刪除

盡管系列對(duì)象應(yīng)該是大小不可變的,但有可能在原地追加、插入和刪除元素,但所有這些操作都是:

  • 緩慢,因?yàn)樗鼈冃枰獮檎麄€(gè)對(duì)象重新分配內(nèi)存并更新索引;
  • 痛苦的不方便。

下面是插入數(shù)值的一種方式和刪除數(shù)值的兩種方式:

圖片圖片

第二種刪除值的方法(通過(guò)刪除)比較慢,而且在索引中存在非唯一值的情況下可能會(huì)導(dǎo)致復(fù)雜的錯(cuò)誤。

Pandas有df.insert方法,但它只能將列(而不是行)插入到數(shù)據(jù)框架中(而且對(duì)序列根本不起作用)。

另一種追加和插入的方法是用iloc對(duì)DataFrame進(jìn)行切片,應(yīng)用必要的轉(zhuǎn)換,然后用concat把它放回去。pdi中實(shí)現(xiàn)了一個(gè)叫做insert的函數(shù),可以自動(dòng)完成這個(gè)過(guò)程:

圖片圖片

注意,(就像在df.insert中一樣)插入的位置是由0<=i<=len(s)的位置給出的,而不是由索引中的元素的標(biāo)簽。

你可以為一個(gè)新元素提供一個(gè)標(biāo)簽。對(duì)于一個(gè)非數(shù)字性的索引,它是必須的。例如:

圖片圖片

要通過(guò)標(biāo)簽指定插入點(diǎn),你可以把pdi.find和pdi.insert結(jié)合起來(lái),如下圖所示:

圖片圖片

注意,與df.insert不同,pdi.insert返回一個(gè)副本,而不是在原地修改Series/DataFrame。

統(tǒng)計(jì)數(shù)據(jù)

Pandas提供了全方位的統(tǒng)計(jì)功能。它們可以深入了解百萬(wàn)元素系列或數(shù)據(jù)框架中的內(nèi)容,而無(wú)需手動(dòng)滾動(dòng)數(shù)據(jù)。

所有的Pandas統(tǒng)計(jì)函數(shù)都會(huì)忽略NaN,如下圖所示:

圖片圖片

注意,Pandas std給出的結(jié)果與NumPy std不同。

由于系列中的每個(gè)元素都可以通過(guò)標(biāo)簽或位置索引來(lái)訪問(wèn),所以有一個(gè)argmin(argmax)的姐妹函數(shù),叫做idxmin(idxmax),如圖所示:

圖片圖片

下面是Pandas的自描述性統(tǒng)計(jì)函數(shù)的列表,供參考:

  • std,樣本標(biāo)準(zhǔn)差;
  • var,無(wú)偏方差;
  • sem,無(wú)偏標(biāo)準(zhǔn)誤差的平均值;
  • quantile,樣本四分位數(shù)(s.quantile(0.5) ≈ s.median());
  • mode,即出現(xiàn)頻率最高的值;
  • nlargest和nsmallest,默認(rèn)情況下,按外觀順序排列;
  • diff,第一次離散差分;
  • cumsum和cumprod,累積和,以及乘積;
  • cummin和cummax,累積最小和最大。

還有一些更專業(yè)的統(tǒng)計(jì)功能:

  • pct_change,當(dāng)前和前一個(gè)元素之間的變化百分比;
  • skew,無(wú)偏差的偏度(第三時(shí)刻);
  • kurt 或 kurtosis,無(wú)偏的谷度(第四時(shí)刻);
  • cov,corr 和 autocorr,協(xié)方差,相關(guān),和自相關(guān);
  • rolling、加權(quán)和指數(shù)加權(quán)的窗口。

重復(fù)數(shù)據(jù)

特別注意檢測(cè)和處理重復(fù)的數(shù)據(jù),可以在圖片中看到:

is_unique,nunique, value_countsis_unique,nunique, value_counts

drop_duplicates 和 duplicated 可以保留最后出現(xiàn)的,而不是第一個(gè)。

請(qǐng)注意,s.unique()比np.unique要快(O(N)vs O(NlogN)),它保留了順序,而不是像np.unique那樣返回排序后的結(jié)果。

缺失值被當(dāng)作普通值處理,這有時(shí)可能會(huì)導(dǎo)致令人驚訝的結(jié)果。

圖片圖片

如果想排除NaN,你需要明確地做到這一點(diǎn)。在這個(gè)特殊的例子中,s.dropna().is_unique == True。

還有一個(gè)單調(diào)函數(shù)家族:

  • s.is_monotonic_increasing()、
  • s.is_monotonic_decreasing()、
  • s._strict_monotonic_increasing()、
  • s._string_monotonic_decreasing()
  • s.is_monotonic() - 這是s.is_monotonic_increasing()的同義詞,對(duì)于單調(diào)下降的序列返回False!

字符串和正則表達(dá)式

幾乎所有的Python字符串方法在Pandas中都有一個(gè)矢量的版本:

count, upper, replacecount, upper, replace

當(dāng)這樣的操作返回多個(gè)值時(shí),有幾個(gè)選項(xiàng)來(lái)決定如何使用它們:

split, join, explodesplit, join, explode

如果知道正則表達(dá)式,Pandas也有矢量版本的常用操作:

findall, extract, replacefindall, extract, replace

Group by

在數(shù)據(jù)處理中,一個(gè)常見(jiàn)的操作是計(jì)算一些統(tǒng)計(jì)數(shù)據(jù),而不是對(duì)整個(gè)數(shù)據(jù)集,而是對(duì)其中的某些組。第一步是通過(guò)提供將一個(gè)Series(或一個(gè)DataFrame)分成若干組的標(biāo)準(zhǔn)來(lái)建立一個(gè)惰性對(duì)象。這個(gè)惰性的對(duì)象沒(méi)有任何有意義的表示,但它可以是:

  • 迭代(產(chǎn)生分組鍵和相應(yīng)的子系列--非常適合于調(diào)試):

groupbygroupby

  • 以與普通系列相同的方式進(jìn)行查詢,以獲得每組的某個(gè)屬性(比迭代快):

圖片圖片

所有操作都不包括NaNs

在這個(gè)例子中,根據(jù)數(shù)值除以10的整數(shù)部分,將系列分成三組。對(duì)于每一組,要求提供元素的總和,元素的數(shù)量,以及每一組的平均值。

除了這些集合功能,還可以根據(jù)特定元素在組內(nèi)的位置或相對(duì)價(jià)值來(lái)訪問(wèn)它們。下面是這種情況:

min, median, max, first, nth, lastmin, median, max, first, nth, last

你也可以用g.agg(['min', 'max'])一次計(jì)算幾個(gè)函數(shù),或者用g.describe()一次顯示一大堆的統(tǒng)計(jì)函數(shù)。

如果這些還不夠,也可以通過(guò)自己的Python函數(shù)傳遞數(shù)據(jù)。它可以是

  • 用g.apply(f)接受一個(gè)組x(一個(gè)系列對(duì)象)并生成一個(gè)單一的值(如sum())的函數(shù)f。
  • 一個(gè)函數(shù)f接受一個(gè)組x(一個(gè)系列對(duì)象),并用g.transform(f)生成一個(gè)與x相同大小的系列對(duì)象(例如,cumsum())。

圖片圖片

在上面的例子中,輸入的數(shù)據(jù)被排序了。這對(duì)于groupby來(lái)說(shuō)是不需要的。實(shí)際上,如果組內(nèi)元素不是連續(xù)存儲(chǔ)的,它也同樣能工作,所以它更接近c(diǎn)ollections.defaultdict而不是itertools.groupby。而且它總是返回一個(gè)沒(méi)有重復(fù)的索引。

圖片圖片

與defaultdict和關(guān)系型數(shù)據(jù)庫(kù)的GROUP BY子句不同,Pandas groupby是按組名排序的。它可以用sort=False來(lái)禁用,如下代碼所示:

>>> s = pd.Series([1, 3, 20, 2, 10])
>>> for k, v in s.groupby(s//10, sort=False):
       print(k, v.tolist())
0 [1, 3, 2]
2 [20]
1 [10]

參考資料

[1]Pandas: https://pandas.pydata.org/

[2]Polars: https://www.pola.rs/

[3]pdi: https://github.com/axil/pandas-illustrated

[4]該功能: https://pandas.pydata.org/docs/reference/api/pandas.Flags.allows_duplicate_labels.html

[5]問(wèn)題#19205: https://github.com/numpy/numpy/issues/19205

責(zé)任編輯:武曉燕 來(lái)源: 數(shù)據(jù)STUDIO
相關(guān)推薦

2023-07-31 11:44:38

Pandas性能數(shù)組

2021-08-17 09:55:50

pandas 8indexPython

2011-08-29 16:08:11

MIUI小米手機(jī)

2011-03-30 11:00:53

Windows 8

2024-11-26 08:00:00

SQLPandasPandaSQL

2020-03-10 08:55:50

PandasNumPy函數(shù)

2023-07-06 14:49:44

PandasPolars語(yǔ)法

2023-10-15 17:07:35

PandasPython庫(kù)

2020-04-24 15:47:31

互聯(lián)網(wǎng)公司裁員

2022-07-14 09:24:28

大數(shù)據(jù)技術(shù)

2023-05-05 18:45:21

Python人工智能機(jī)器學(xué)習(xí)

2023-11-30 15:53:43

2021-06-08 09:18:54

SQLPandas數(shù)據(jù)透視表

2010-09-15 13:54:36

WidgetOPhone

2012-12-14 14:48:01

諾基亞Series 40S40

2021-01-22 05:53:08

C# IndexRange

2022-06-17 10:52:01

數(shù)據(jù)存儲(chǔ)采集

2013-01-25 15:19:07

Series 40S40

2009-11-16 11:03:44

Oracle INDE

2020-04-03 13:50:19

數(shù)據(jù)分析PandasNumPy
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)