1. 什么是Series?
Series是一種類似于一維數組的對象,與一維數組對象不同的是Series帶有標簽(索引),通俗來說就是一維帶標簽(索引)的一維數組。如下圖所示:

帶有索引的一維數組
2. 如何創建Series?
Series是一維帶標簽(索引)的一維數組,對于Series最關鍵的也就是索引index和與之對應的value值。
一般格式 (這里的data就是value值的集合):
s = pd.Series( data , index )
data幾種常見的取值類型:
- 標量值、list列表;
- ndarray對象;
- dict字典;
index取值規范:
- 索引值必須是可hashable的(如果一個對象是可散列的,那么在這個對象的生命周期中,他的散列值是不會變的(它需要實現__hash__()方法)),并且索引index的長度必須和value值的長度一致,如果不一致會拋出異常(這點需要格外的注意);
- 如果不設置索引,默認索引是從0到n-1的序列值[其中n為data值的長度];
- 如果data的類型為dict字典類型,對應的字典中的key值就是對應series對象中的index值;
- 相同的索引值也是可以的;
下面依照著data的幾種常見的類型來分別介紹,中間會穿插著index的取值規范問題:
2.1 data為標量值、list列表
#data:標量值1
#index:不指定(默認索引)
import pandas as pd
s = pd.Series(1)
print(s)
result:
0 1
dtype: int64
#data:list列表
#index:通過list列表指定,其中data和index長度一致
import pandas as pd
s = pd.Series([1,2,3,4,5],index = ["a","a","c","d","e"])
print(s)
result:
a 1
a 2
c 3
d 4
e 5
dtype: int64
注意:
- 當創建Series對象的時候指定index的時候,index元素個數(此處的index為一個list列表)要和data中元素個數相等;
- 使用相同的索引值"a",程序并沒有發生異常,索引值可以是相同的;
2.2 data為ndarray對象
import numpy as np
import pandas as pd
data = np.arange(5)
#使用list作為index索引
index2 = ["a","b","c","d","e"]
#使用ndarray數組作為index索引
index3 = np.array(["a","b","c","d","e"])
s = pd.Series(data)
s2 = pd.Series(data,index2)
s3 = pd.Series(data,index3)
print(s)
print("-"*6)
print(s2)
print("-"*6)
print(s3)
result:
0 0
1 1
2 2
3 3
4 4
dtype: int32
------
a 0
b 1
c 2
d 3
e 4
dtype: int32
------
a 0
b 1
c 2
d 3
e 4
dtype: int32
注意:
- 此時的data是ndarray數組類型,而index分別指定了無參數的默認index索引、指定list列表以及指定ndarray數組類型的index。
2.3 data為dict字典
import pandas as pd
d = {"a":0,"b":1,"c":2}
s = pd.Series(d)
print(s)
result:
a 0
b 1
c 2
dtype: int64
這里由于將data位置的參數傳入字典,將字典的鍵作為了Series對象的index,所以如果再次指定index的時候會出現一些新的情況:
- 指定的index中不包含字典中的鍵值;
- 指定的index中包含部分字典中的鍵值;
- 指定的index中包含全部的字典中鍵值;
下面就使用代碼簡單的介紹一下這三種情況。
- 指定的index中不包含字典中的鍵值
import pandas as pd
d = {"a":0,"b":1,"c":2}
s = pd.Series(d,index = ["d","e"])
print(s)
result:
d NaN
e NaN
dtype: float64
- 指定的index中包含部分字典中的鍵值
import pandas as pd
d = {"a":0,"b":1,"c":2}
s = pd.Series(d,index = ["a","d"])
print(s)
result:
a 0.0
d NaN
dtype: float64
- 指定的index中包含全部的字典中鍵值
import pandas as pd
d = {"a":0,"b":1,"c":2}
s = pd.Series(d,index = ["a","b","c"])
print(s)
result:
a 0
b 1
c 2
dtype: int64
總結:
我們知道創建Series對象的一般格式,包含兩個參數data和index索引。我們使用Python字典作為創建Series的data,同時我們知道當將字典作為創建Series對象的data的話,Python字典中的key可以作為Series的index,但是此時我們仍然可以繼續指定index,通過上面的三種情況的描述,可以得出結論,使用字典創建Series,同時指定index的話,此時的index起到一個篩選的作用,最終的輸出結果就是指定的index,如果指定的index在字典中的key中,則將對應的值關聯到指定的index中;如果指定的index不在字典中的key中,則將NaN關聯到指定index中。由于Python中字典中的key不能夠重復,所以雖然Series允許使用有重復的index值,但是如果使用字典創建Series的時候肯定不會有相同的index值。
3. Series的屬性
此處介紹Series屬性包括兩個方面(因為此處介紹的是Series的屬性不是Series的方法,所以不要在后面加小括號):
- 獲取Series的index索引和value值,順便介紹統計index和value相同類別的個數的方法;
- 獲取Series的名稱以及index的名稱;
#實驗所用到的Series對象
import pandas as pd
s = pd.Series([1,2,3],index = ["a","b","a"])
print(s)
3.1 獲取index索引和value值,并統計index和value相同類別的個數
下面將index和value分開來介紹:
#獲取Series的索引
print(s.index)
result:
Index(['a', 'b', 'a'], dtype='object')
此時返回的索引是一個迭代器對象,這個對象還可能會有其他的屬性。如果我們想要獲取其中的具體值的話,可以使用for循環進行遍歷,還可以使用下面這些簡單的屬性將迭代轉換為ndarray數組或者是list列表:
print(s.index.values)
print(type(s.index.values))
print("-"*6)
print(list(s.index.values))
print(type(list(s.index.values)))
result:
['a' 'b' 'a']
<class 'numpy.ndarray'>
------
['a', 'b', 'a']
<class 'list'>
如果我們想要統計Series中索引相同索引的個數,可以使用下面的方法(注意此時是方法不在是屬性了):
print(s.index.value_counts())
result:
a 2
b 1
dtype: int64
values其實和index類似,下面簡單的介紹一下:
print(s.values)
print(type(s.values))
result:
[1 2 3]
<class 'numpy.ndarray'>
與獲取index不同的是,使用s.values返回的就是包含值的ndarray數組類型。下面統計相同value值的個數,同樣這個也是一個方法,這個方法還是很常用的:
print(s.value_counts())
result:
3 1
2 1
1 1
dtype: int64
3.2 獲取Series的名稱以及index的名稱
Series有本身以及index和value,除了value沒有名稱外,Series本身和index都可以指定名稱,如果不指定的話默認為None。
s.name = "my Series"
s.index.name = "my index"
print(s)
result:
my index
a 1
b 2
a 3
Name: my Series, dtype: int64
4. Series的索引獲取指定值
Series簡單來說就是帶有索引的一維數組,我們很自然的可以通過索引來獲取對應的value值,我們有三種方式進行索引:
- 位置索引。通過0 ~ n-1[n為Series中索引個數]進行索引;
- 名稱索引。通過傳入指定的index名稱來進行索引;
- 獲取單個索引值;
- 獲取多個索引值;
- 點索引。通過".index名稱"的形式進行索引;
下面來分別介紹這三種索引方式以及需要注意的地方。
import pandas as pd
s = pd.Series([1,2,3,4],index = ["a","b","c","d"])
print(s)
4.1 位置索引
# 位置索引
print(s[0])
print(s[-1])
print(s[2])
result:
1
4
3
此處的位置索引類似python中的list列表,不僅能夠正向索引[從0開始]而且還能夠反向索引[從-1開始反向索引]。
4.2 名稱索引
# index名稱索引
#獲取單個索引值
print(s["a"])
print("*"*6)
#獲取多個索引值
print(s[["a","b","c"]])
result:
1
******
a 1
b 2
c 3
dtype: int64
使用名稱索引不僅可以索引單個value值,也可以索引多個value值。平時用的最多的就是位置索引和名稱索引,說一說使用他們的時候需要注意的地方:
- 我們知道Series的index索引可以是任意類型,如果index為整數類型,那么位置索引就會失效。
import pandas as pd
s = pd.Series(["a","b","c","d"],index = [1,3,4,5])
# 此處使用位置索引會拋出異常KeyError
# print(s[-1])
# print(s[2])
#此處得到的結果是名稱索引
print(s[3])
result:
b
- 由于Series的index是可以重復的,對于位置索引來說無論index是否重復都與索引沒有關系,但是如果使用名稱索引的話,索引出來的是結果是一個具有相同index的Series對象。
import pandas as pd
s = pd.Series(["a","b","c","d"],index = [1,1,4,5])
# 此處使用的是名稱索引
print(s[1])
result:
1 a
1 b
dtype: object
4.3 點索引
平時使用名稱索引以及位置索引足夠使用。點索引使用有很多局限性:
- 點索引只使用于Series的index類型為非數值類型才可以使用;
- 如果Series中的index中有一些索引名稱與Python的一些關鍵字或者一些函數名重名的話,會導致無法獲取Series的值;
import pandas as pd
# 此時的index為數值類型
s = pd.Series(["a","b","c","d"],index = [1,2,3,4])
# 會拋出語法錯誤的異常SyntaxError
# print(s.2)
import pandas as pd
# 此時的index為數值類型
s = pd.Series([1,2,3,4],index = ["a","b","c","def"])
# 通過點索引獲取value值
print(s.a)
# 會拋出語法錯誤的異常SyntaxError
# print(s.def)
result:
1
5. Series的切片slice
通過Series的切片來獲取連續的多個索引對應的值,Series的切片有兩種方式:
- 使用位置切片,類似s[start_index : end_index],熟悉python都知道這種切片方式,需要注意的這種方式切片同樣是包左不包右;
- 使用名稱切片,類似s [start_index_name , end_index_name],這種方式和上面使用位置切片的最大區別就是名稱切片,即包左又包右;
import pandas as pd
s = pd.Series([1,2,3,4],index = ["a","b","c","d"])
print(s)
result:
a 1
b 2
c 3
d 4
dtype: int64
5.1 位置切片
# 使用位置切片
print(s[0:2])
result:
a 1
b 2
dtype: int64
5.2 名稱切片
# 使用名稱切片
print(s["b":"d"])
result:
b 2
c 3
d 4
dtype: int64
注意:
在上面的索引方式,我們知道了位置索引和名稱索引在index為數值類型時候的不同,當index為數值類型的時候,使用位置索引會拋出keyerror的異常,也就是說當index為數值類型的時候,索引使用的是名稱索引。但是在切片的時候,有很大的不同,如果index為數值類型的時候,切片使用的是位置切片。總的來說,當index為數值類型的時候:
- 進行索引的時候,相當于使用的是名稱索引;
- 進行切片的時候,相當于使用的是位置切片;
6. Series的增刪改查
6.1 添加Series的值(增)
為Series添加新的值的方式有兩種:
- 使用series.Append(pd.Series(data,index))的方式添加,這種方式會返回一個新的Series對象,這種方式最大的特點就是可以添加多個Series值;
- 使用series["new_index"] = value的方式添加,這種方式會直接在原來的Series上進行修改,并且這種方式每次只能夠添加一個Series值;
import pandas as pd
s = pd.Series(1,index =["a"])
print(s)
print("*"*6)
# 使用append方式添加多個Series值
# 此處將返回的值賦值給了原來的Series,因為使用append添加的話返回的是新的Series對象
s = s.append(pd.Series([2,3],index = ["b","c"]))
print(s)
print("*"*6)
# 使用s[new_index] = value方式添加
s["d"] = 4
print(s)
result:
a 1
dtype: int64
******
a 1
b 2
c 3
dtype: int64
******
a 1
b 2
c 3
d 4
dtype: int64
6.2 刪除series的值(刪)
刪除直接使用del關鍵字刪除即可。
import pandas as pd
s = pd.Series([1,2,3,4],index = ["a","b","c","d"])
print(s)
print("*"*6)
del s["b"]
print(s)
result:
a 1
b 2
c 3
d 4
dtype: int64
******
a 1
c 3
d 4
dtype: int64
6.3 通過索引修改Series的值(改)
其實此時介紹的修改Series的值和在4中介紹的一致,只不過將4中介紹的獲取到的Series值進行重新的賦值即是修改對應Series的值,因此此處也有三種方式:
- 通過位置索引修改value值;
- 通過名稱索引修改value值;
- 通過點索引修改value值;
此處因為類似,所以只選擇一個進行實驗:
import pandas as pd
s = pd.Series([1,2,3,4],index = ["a","b","c","d"])
s["a"] = 100
print(s)
result:
a 100
b 2
c 3
d 4
dtype: int64
6.4 判斷索引是否在Series中(查)
判斷index是否在Series中很簡單,其實和python中查看元素是否在list列表中的方法是一樣的。
import pandas as pd
s = pd.Series([1,2,3,4],index = ["a","b","c","d"])
print("a" in s)
print("q" in s)
result:
True
False
7. 過濾Series的值
我們可以通過布爾選擇器,也就是條件篩選來過濾一些特定的值,從而僅僅獲取滿足條件的值。過濾Series的值的方式分為兩種:
- 單條件篩選;
- 多條件篩選;
import pandas as pd
s = pd.Series([1,2,3,4],index = ["a","b","c","d"])
7.1 單條件篩選
print("-"*5 + "布爾選擇器" + "-"*5)
print(s < 3)
print("-"*5 + "單條件查詢" + "-"*5)
print(s[s<3])
result:
-----布爾選擇器-----
a True
b True
c False
d False
dtype: bool
-----單條件查詢-----
a 1
b 2
dtype: int64
7.2 多條件查詢
print("-"*5 + "多條件查詢" + "-"*5)
print(s[(s > 2) & (s < 4) ])
result:
-----多條件查詢-----
c 3
dtype: int64
注意:
- 多條件查詢中的and以及or必須使用對應的符號來表示,and用&,or用|來表示;
- 使用多條件的時候,為了避免出錯,在每個條件上最好加上括號;
8. Series缺失值的處理
- 判斷Value值是否為缺失值,isnull()判斷series中的缺失值以及s.notnull()判斷series中的非缺失值;
- 刪除缺失值
- 使用dropna();
- 使用isnull()以及notnull();
- 填充缺失值
- 使用fillna;
- 使用指定值填充缺失值;
- 使用插值填充缺失值;
- 向前填充ffill;
- 向后填充bfill;
- 使用fillna;
# 創建一個帶缺失值的Series
import pandas as pd
s = pd.Series([1,2,None,4])
print(s)
result:
0 1.0
1 2.0
2 NaN
3 4.0
dtype: float64
8.1 判斷value值是否為缺失值
有兩種方式判斷:
- s.isnull()判斷s中的缺失值;
- s.notnull()判斷s中的非缺失值;
# 缺失值的地方為True
print("-"*5 + "使用s.isnull判斷" + "-"*5)
print(s.isnull())
#缺失值的地方為False
print("-"*5 + "使用s.notnull判斷" + "-"*5)
print(s.notnull())
result:
-----使用s.isnull判斷-----
0 False
1 False
2 True
3 False
dtype: bool
-----使用s.notnull判斷-----
0 True
1 True
2 False
3 True
dtype: bool
8.2 刪除缺失值
- 使用dropna()方法刪除缺失值,返回新的Series對象;
- 使用series.isnull()以及series.notnull()方法,使用布爾篩選進行過濾出非缺失值;
print("-"*5 + "使用dropna()刪除所有的缺失值" + "-"*5)
print(s.dropna())
print("-"*5 + "使用isnull()刪除所有的缺失值" + "-"*5)
print(s[~s.isnull()])
print("-"*5 + "使用notnull()刪除所有的缺失值" + "-"*5)
print(s[s.notnull()])
result:
-----使用dropna()刪除所有的缺失值-----
0 1.0
1 2.0
3 4.0
dtype: float64
-----使用isnull()刪除所有的缺失值-----
0 1.0
1 2.0
3 4.0
dtype: float64
-----使用notnull()刪除所有的缺失值-----
0 1.0
1 2.0
3 4.0
dtype: float64
8.3 使用fillna()填充缺失值
- 使用指定值填充缺失值;
- 使用插值填充缺失值;
print("-"*5 + "原來的Series" + "-"*5)
print(s)
print("-"*5 + "指定填充值0" + "-"*5)
print(s.fillna(value = 0))
print("-"*5 + "向前填充ffill" + "-"*5)
print(s.fillna(method = "ffill"))
print("-"*5 + "向后填充bfill" + "-"*5)
print(s.fillna(method = "bfill"))
result:
-----原來的Series-----
0 1.0
1 2.0
2 NaN
3 4.0
dtype: float64
-----指定填充值0-----
0 1.0
1 2.0
2 0.0
3 4.0
dtype: float64
-----向前填充ffill-----
0 1.0
1 2.0
2 2.0
3 4.0
dtype: float64
-----向后填充bfill-----
0 1.0
1 2.0
2 4.0
3 4.0
dtype: float64
注意:
默認情況下,填充缺失值都會創建一個新的Series對象,如果希望直接在原來的Series上進行修改的話,可以使用下面兩種方式:
- 直接進行賦值;
- 給fillna()函數添加一個新的參數,inplace = True參數;
9. Series排序
series的排序有兩種:
- 根據索引進行排序,使用series.sort_index(ascending = True);
- 根據值進行排序,使用series.sort_value(ascending = True);
10. Series的描述性統計

Series的描述性統計
更多原創干貨,歡迎關注我的知乎"觸摸壹縷陽光"以及公眾號"AI機器學習與深度學習算法"