1. 程式人生 > >第3章 Pandas資料處理(3.1-3.2)_Python資料科學手冊學習筆記

第3章 Pandas資料處理(3.1-3.2)_Python資料科學手冊學習筆記

第2章介紹的NumPy和它的ndarray物件. 為多維陣列提供了高效的儲存和處理方法. Pandas是在NumPy的基礎上建立的新程式庫, 提供DataFrame資料結構. DataFrame帶行標籤(索引),列標籤(變數名),支援相同資料型別和缺失值的多維陣列. 和電子表格很像. NumPy的ndarray提供處理資料常見功能. 但對比如新增標籤,處理缺失值,分組,透視等處理起來較難.

3.1 Pandas安裝

使用Anaconda, Pandas已經安裝好.

檢測Pandas版本號

import pandas as pd
import numpy as np
print(pd.__version__,
np.__version__) # 不是vision
0.23.0 1.14.3

3.2 Pandas物件介紹

Pandas三個基礎資料結構 : Series, DataFrame, Index (注意字母大小寫)

3.2.1 Pandas的 Series物件

Series是一個帶索引資料的一維陣列

# 可以用一個數組建立Series物件
data1 = pd.Series([0.25,0.5,0.75,1])
data2 = np.array([0.25,0.5,0.75,1])
data3 = [0.25,0.5,0.75,1]
print("data1的資料型別是:"
,type(data1),'---',data1) print("data2的資料型別是:",type(data2),'---',data2) print("data3的資料型別是:",type(data3),'---',data3)
data1的資料型別是: <class 'pandas.core.series.Series'> --- 0    0.25
1    0.50
2    0.75
3    1.00
dtype: float64
data2的資料型別是: <class 'numpy.ndarray'> --- [0.25 0.5  0.75 1.  ]
data3的資料型別是: <class 'list'> --- [0.25, 0.5, 0.75, 1]

從上面輸出結構看,Series將一組資料和一組索引繫結在一起,可用values屬性和index屬性屬性獲取. (注意字母大小寫和是否為複數格式)

data1.values
array([0.25, 0.5 , 0.75, 1.  ])
data1.index
RangeIndex(start=0, stop=4, step=1)

可以通過中括號索引標籤獲取值

data1[2]  # 第3個數值
0.75
data1[1:3]  # 第2-3個  ,含左不含右
1    0.50
2    0.75
dtype: float64
data[:3]   # 前3個
0    0.25
1    0.50
2    0.75
dtype: float64

Series和NumPy的一維陣列基本相同, 本質差別在索引上. NumPy陣列是***隱式定義***的***整數索引***獲取數值, 而Pandas的Series物件用一種***顯示定義***的索引與數值關聯.

顯示索引 : 索引不僅僅是整數, 還可以是***任何想要的型別***.

data = pd.Series([0.25,0.5,0.75,1,'nihao'],index=['a','a','c','d',100])
data
a       0.25
a        0.5
c       0.75
d          1
100    nihao
dtype: object

Series陣列中索引和數值都可以是不同型別的. 而NumPy中陣列型別必須是同類型的. Series陣列中索引值可以相同.

Series是特殊的字典 - 可以把Pandas的Series物件看成是一種特殊的Python字典. - NumPy的陣列比Python列表高效. Pandas Series物件在某些操作上比Python的字典高效.

用Python的字典建立一個Series物件. 用字典建立Series物件是, 其索引預設按照順序排列.

rk_dict = {'湖北':23213,
             '湖南':213323,     # 用冒號 而不是逗號
             '廣東':233232,
             '江西':8238238,
             '山東':992329}
rk = pd.Series(rk_dict)
rk
湖北      23213
湖南     213323
廣東     233232
江西    8238238
山東     992329
dtype: int64
rk['湖北']
23213

和字典不同, Series物件還支援陣列形式的操作. - 首先, Series不是字典 - 字典不能執行陣列形式的操作?

rk['湖北':'廣東']
湖北     23213
湖南    213323
廣東    233232
dtype: int64

建立Series物件的方法: - pd.Series(data, index=index) - index是一個可選引數, data引數支援多種資料型別

data可以是類表(list)或NumPy陣列

pd.Series([2,4,6,8])
0    2
1    4
2    6
3    8
dtype: int64

data可以是一個標量, 建立Series時會重複填充到每個索引上

pd.Series(5,index=[100,200,300])
100    5
200    5
300    5
dtype: int64

data還可以是一個字典, index預設排序方式是字典鍵

pd.Series({2:'a',3:'b',4:'d'})
2    a
3    b
4    d
dtype: object

通過顯示索引進行篩選

pd.Series({2:'a',3:'b',4:'d'},index=[4,2])
4    d
2    a
dtype: object

3.2.2 Pandas的DataFrame物件

可以將Series類比為靈活的索引的一維陣列,那麼DataFrame就可以看作一個就有靈活行***索引***, 又有靈活***列名***的二維陣列.

rk_dict = {'湖北':23213,
             '湖南':213323,     # 用冒號 而不是逗號
             '廣東':233232,
             '江西':8238238,
             '山東':992329}
rk = pd.Series(rk_dict)

sh_dict = {'湖北':'武漢',
           '湖南':'長沙',     
             '廣東':'廣州',
             '江西':'南昌',
             '山東':'濟南'}
sh = pd.Series(sh_dict)
print(rk)
print(sh)
湖北      23213
湖南     213323
廣東     233232
江西    8238238
山東     992329
dtype: int64
湖北    武漢
湖南    長沙
廣東    廣州
江西    南昌
山東    濟南
dtype: object

用上面的兩個Series物件定義一個DataFrame

states = pd.DataFrame({'省會':sh,
                       '人口':rk})
states
省會 人口
湖北 武漢 23213
湖南 長沙 213323
廣東 廣州 233232
江西 南昌 8238238
山東 濟南 992329

和Series一樣,DataFrame也有index屬性可以獲取索引(行標籤)的標籤

states.index
Index(['湖北', '湖南', '廣東', '江西', '山東'], dtype='object')

DataFrame有columns屬性,存放列標籤Index物件. 注意複數和字母大小寫

states.columns
Index(['省會', '人口'], dtype='object')

DataFrame的特點是列也有索引, 所以資料可以通過行/列索引獲得.

DataFrame是特殊的字典

字典是一個鍵對映一個值, DataFrame是一列對映一個Series的資料. 也就是索引列標籤的話, 返回一列資料

print(states['省會'])  # 為什麼結果把行索引也都帶出了呢 ?
# print(states['湖北'])  報錯
湖北    武漢
湖南    長沙
廣東    廣州
江西    南昌
山東    濟南
Name: 省會, dtype: object

建立DataFrame物件

方式1 : 通過單個Series物件建立

pd.DataFrame(rk,columns=['人口'])
# rk是個Series物件,沒有列標籤. DataFrame是有列標籤的, 所以需要指定.
# 人口需要用中括號[],不能用小括號
人口
湖北 23213
湖南 213323
廣東 233232
江西 8238238
山東 992329

方式2 : 通過字典建立(應該是用字典,列表建立)

data = [{'a': i, 'b': 2*i} for i in range(3)] 
print(data)
print(type(data))
# 這是建立了一個list, list裡面有三個字典元素? 
data1 = pd.DataFrame(data)
print(data1)
[{'a': 0, 'b': 0}, {'a': 1, 'b': 2}, {'a': 2, 'b': 4}]
<class 'list'>
   a  b
0  0  0
1  1  2
2  2  4

從上程式碼可以看出, 當用字典建立DataFrame的時候, 原字典的關鍵字變成了DataFrame中的列(columns)

pd.DataFrame([{'a':1,'b':100},{'b':1000,'a':12},{'b':123,'c':"湖北"},{'a':1000}])
a b c
0 1.0 100.0 NaN
1 12.0 1000.0 NaN
2 NaN 123.0 湖北
3 1000.0 NaN NaN
x1 = {'a':1,'b':100,'a':100}      # 兩個a, 居然不報錯,但是輸出的結果中a只有一個
x1
{'a': 100, 'b': 100}

方式3 : 通過Series建立

rk_dict = {'湖北':23213,
             '湖南':213323,     # 用冒號 而不是逗號
             '廣東':233232,
             '江西':8238238,
             '山東':992329}     #注意 山東在 sh中沒有
rk = pd.Series(rk_dict)

sh_dict = {'湖北':'武漢',
           '湖南':'長沙',     
             '廣東':'廣州',
             '江西':'南昌',
             '廣西':'南寧'}      #注意廣西在rk中沒有
sh = pd.Series(sh_dict)
pd.DataFrame({'人口':rk,'省會':sh})
人口 省會
山東 992329.0 NaN
廣東 233232.0 廣州
廣西 NaN 南寧
江西 8238238.0 南昌
湖北 23213.0 武漢
湖南 213323.0 長沙

方式4 : 通過NumPy二維陣列建立

pd.DataFrame(np.random.rand(3,2),columns=['x1','x2'],index = ['a','b','c'])
x1 x2
a 0.922554 0.996392
b 0.878324 0.389322
c 0.835772 0.593807

方式5 : 通過NumPy結構化陣列建立. 在2.9節中介紹

A = np.zeros(3,dtype=[('a','i8'),('b','f8')])
print(A)
print(type(A))
A
[(0, 0.) (0, 0.) (0, 0.)]
<class 'numpy.ndarray'>





array([(0, 0.), (0, 0.), (0, 0.)], dtype=[('a', '<i8'), ('b', '<f8')])
pd.DataFrame(A)     #  無縫連線?
a b
0 0 0.0
1 0 0.0
2 0 0.0

3.2.2 Pandas的Index物件

Index可以看作是一個不可變陣列或有序集合

ind = pd.Index([2,3,4,7,11])
ind
Int64Index([2, 3, 4, 7, 11], dtype='int64')

將Index看作是不可變陣列

ind[1]
3
ind[::2]
Int64Index([2, 4, 11], dtype='int64')
ind[1] = 0   # 值不可修改?
---------------------------------------------------------------------------

TypeError                                 Traceback (most recent call last)

<ipython-input-77-906a9fa1424c> in <module>()
----> 1 ind[1] = 0


D:\Anaconda3\lib\site-packages\pandas\core\indexes\base.py in __setitem__(self, key, value)
   2048 
   2049     def __setitem__(self, key, value):
-> 2050         raise TypeError("Index does not support mutable operations")
   2051 
   2052     def __getitem__(self, key):


TypeError: Index does not support mutable operations

Index物件遵循Python標準庫集合(set)資料結構的許多習慣用法,包括並集,交集,差集等.

inda = pd.Index([1,3,5,7,9])
indb = pd.Index([2,4,5,9,10])
print(inda & indb)   # 交集
print(inda | indb)  #並集
print(inda ^ indb)   # 異或
Int64Index([5, 9], dtype='int64')
Int64Index([1, 2, 3, 4, 5, 7, 9, 10], dtype='int64')
Int64Index([1, 2, 3, 4, 7, 10], dtype='int64')