小白學 Python 數據分析(3):Pandas (二)數據結構 Series


在家為國家做貢獻太無聊,不如跟我一起學點 Python

順便問一下,你們都喜歡什么什么樣的文章封面圖,老用這一張感覺有點丑

人生苦短,我用 Python

前文傳送門:

小白學 Python 數據分析(1):數據分析基礎

小白學 Python 數據分析(2):Pandas (一)概述

引言

先介紹下 Pandas 的數據結構,畢竟數據結構是萬物的基礎。

Pandas 有兩種主要的數據結構: Series 和 DataFrame ,本文就先介紹第一種 Series 。

模塊導入

首先我們在代碼中引入 Pandas 和 Numpy ,如下:

import numpy as np
import pandas as pd

Series

Series 可以簡單的理解為一維數組,可以存儲整數、浮點數、字符串、Python 對象等類型的數據。

這個概念有點像 Java 中的集合。

如果無法理解的話,那么可以看下面這個圖(Excel 簡單畫畫,靈魂畫手登場):

這里的 data 可以是上面提到的那些數據類型,並不僅限於圖中的整數。

如果 index 的值未指定,那么將會自動的創建數值類型的索引,從 0 開始,例如:0 , 1 , 2, 3 ... len(data) - 1 。

創建一個 Series ,這里我們可以使用 pd.Series 函數來創建,如下:

s = pd.Series(np.random.rand(5), index=['a', 'b', 'c', 'd', 'e'])
print(s)
print(s.index)

s1 = pd.Series(np.random.randn(5))
print(s1)

結果如下:

a    0.218164
b    0.153201
c    0.572437
d    0.142784
e    0.710664
dtype: float64
Index(['a', 'b', 'c', 'd', 'e'], dtype='object')
0    0.255452
1    1.354357
2    2.092490
3    0.353899
4    1.692989
dtype: float64

從上面我們可以看到,如果我們手動指定了索引,那么將會按照我們指定的索引進行創建,如果沒有指定會直接使用數值索引。

注意: 如果我們手動指定索引,索引的長度必須與數據的長度一致。如果不一致,將會拋出 ValueError 的異常,如下:

s = pd.Series(np.random.rand(6), index=['a', 'b', 'c', 'd', 'e'])

異常部分內容:

ValueError: Length of passed values is 6, index implies 5

字典實例化

Series 是可以使用字典進行實例化的,示例如下:

d = {'b': 1, 'a': 0, 'c': 2}
s2 = pd.Series(d)
print(s2)

結果如下:

b    1
a    0
c    2
dtype: int64

注意: 當我們使用的 data 為字典的時候,且未設置 index 參數時,如果 Python 版本 >= 3.6 且 Pandas 版本 >= 0.23, Series 按字典的插入順序排序索引。Python < 3.6 或 Pandas < 0.23,且未設置 index 參數時, Series 按字母順序排序字典的鍵(key)列表。

在上面的這個示例中,如果當前的環境 Python < 3.6 或 Pandas < 0.23, Series 將會按照字母的順序進行排序,而不是當前字典的順序,輸出的結果將會是 ['a', 'b', 'c']

同時,如果我們在使用字典做 data 的時候,同樣可以設置索引,這樣將會按照索引來提取 data 中對應的值,如果索引在 data 中無對應,將會使用 NaN 來表示缺失的數據,示例如下:

s3 = pd.Series(d, index=['b', 'c', 'd', 'a'])
print(s3)

結果如下:

b    1.0
c    2.0
d    NaN
a    0.0
dtype: float64

標量值實例化

data 還支持標量值進行實例化,當 data 是標量值的時候,實例化 Series 的時候必須提供索引, Series 將會按照索引的長度重復這個標量值,如下:

s4 = pd.Series(5., index=['a', 'b', 'c', 'd', 'e'])
print(s4)

結果如下:

a    5.0
b    5.0
c    5.0
d    5.0
e    5.0
dtype: float64

基於索引的操作方式

print(s[0])
print(s[:3])
print(s[s > s.median()])
print(s[[4, 3, 1]])

結果如下:

0.481205137399224

a    0.481205
b    0.045604
c    0.108321
dtype: float64

d    0.495208
e    0.817171
dtype: float64

e    0.817171
d    0.495208
b    0.045604
dtype: float64

同時, Series 還支持通過索引標簽進行設置值或者是取值,如下:

print(s['a'])
s['e'] = 12.
print(s)

結果如下:

0.481205137399224

a     0.481205
b     0.045604
c     0.108321
d     0.495208
e    12.000000
dtype: float64

如果直接使用 Series 中沒有的索引標簽,會拋出 KeyError 異常:

# 拋出 KeyError 異常
# print(s['f'])

我們可以通過 in 來判斷當前的 Series 中有沒有含有索引標簽,如下:

print('e' in s)
print('f' in s)

結果如下:

True
False

可以通過 get 這個方法獲取 Series 沒有的索引標簽,同時可以設置返回的默認值:

print(s.get('f'))
print(s.get('f', np.nan))

結果如下:

None
nan

常用方法

# 打印 e 的冪次方, e 是一個常數為 2.71828
print (np.exp(s))
# 打印 s 里每個元素的開方
print (np.sqrt(s))
print(s.dtype)
print(s.array)
print(s.to_numpy())

結果如下:

a    1.618023
b    1.046659
c    1.114406
d    1.640840
e    2.264085
dtype: float64

a    0.693690
b    0.213550
c    0.329122
d    0.703711
e    0.903975
dtype: float64

float64

<PandasArray>
[  0.481205137399224, 0.04560362121419126, 0.10832121726528887,
 0.49520848929233285,  0.8171705710254773]
Length: 5, dtype: float64

[0.48120514 0.04560362 0.10832122 0.49520849 0.81717057]

從上面的示例中可以看到,當使用 Series 做一些算數運算的時候,是不需要循環 Series 中每個值的。

注意: Series 之間的操作會自動基於標簽對齊數據。

print(s[1:] + s[:-1])

結果如下:

a         NaN
b    0.091207
c    0.216642
d    0.990417
e         NaN
dtype: float64

操作未對齊索引的 Series, 其計算結果是所有涉及索引的並集。如果在 Series 里找不到標簽,運算結果標記為 NaN,即缺失值。

名稱屬性

Series 支持 name 屬性,我們可以給我們自己定義的 Series 起一個自己喜歡的名字:

s5 = pd.Series(np.random.randn(5), name='my_series')
print(s5)
print(s5.name)
print(id(s5))

結果如下:

0    0.491450
1    0.939965
2    0.868437
3   -0.099575
4    1.866875
Name: my_series, dtype: float64

my_series

1492397351368

這里小編順手使用 id 方法打印一下 s5 的內存地址。

同樣, Series 為我們提供了重命名的方法 rename()

# 重命名 series
s6 = s5.rename("my_series_different")
print(id(s6))

結果如下:

1492397351368
0    0.491450
1    0.939965
2    0.868437
3   -0.099575
4    1.866875
Name: my_series_different, dtype: float64

1492400065800

對比上下兩個 s5 和 s6 可以看到,這兩個 Series 具有相同的 data 內容, name 屬性並不相同。

但是,有一點要注意的是: s5 和 s6 是兩個不同的對象,這里打印的內存地址不同也說明了這一點,這里實際上並不是將 s5 的 name 修改了一下,而是新建了一個新的對象並使用了新的 name 屬性。

示例代碼

老規矩,所有的示例代碼都會上傳至代碼管理倉庫 Github 和 Gitee 上,方便大家取用。

示例代碼-Github

示例代碼-Gitee

參考

https://www.pypandas.cn/docs/getting_started/dsintro.html


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM