1. 程式人生 > >Pandas快速教程-資料結構介紹

Pandas快速教程-資料結構介紹

Pandas中有三種不同型別的資料,為了便於理解,將numpy的ndarray結構也納入進行對比:

型別 維度(dim) 形狀(shape) 元素型別 說明
ndarray(numpy) 1或2 1×0或者n×m 同構 一維的陣列或者多維的矩陣,無索引
Series 1 m×1 非同構 帶索引的一維陣列
DataFrame 2 m×n 非同構 由多個Series組成的二維表,可以理解為Series容器
Panel 3 m×n×h 非同構 三維,可以理解為DataFrame容器(將被更高版本的Pandas遺棄)

Series和DataFrame資料結構的主要屬性:

屬性 說明
index 返回索引
columns 返回欄位名(列名),Series無該屬性,但有name屬性
values 返回索引元素組成的array
dtypes 返回元素型別
ndim 返回維度
shape 返回形狀
size 返回所有元素個數
itemsize 返回每個元素所佔大小(位元組為單位),DataFrame無該屬性

首先構造一個用於演示的DataFrame:

import pandas as pd
import numpy as np

#製造資料:
np.random.seed(100)
data=np.random.randint(1,10,40).reshape(8,-1)
index=pd.date_range('20180901',periods=8)
col=list('ABCDE')
df=pd.DataFrame(data,index=index,columns=col)
print(df)

列印結果:

            A  B  C  D  E
2018-09-01  7  8  1  1  8
2018-09-02  1  5  6  3  2
2018-09-03  3  6  6  1  5
2018-09-04  5  8  6  3  3
2018-09-05  9  9  7  1  1
2018-09-06  8  1  4  5  8
2018-09-07  8  1  2  1  9
2018-09-08  7  8  4  1  6

檢視該物件的屬性:

print('index屬性: ',df.index)
print('我是分割線'.center(80,'='))
print('columns屬性:',df.columns)
print('我是分割線'.center(80,'='))
print('values屬性:',df.values)
print('我是分割線'.center(80,'='))
print('dtypes屬性',df.dtypes)
print('我是分割線'.center(80,'='))
print('ndim屬性:',df.ndim)
print('我是分割線'.center(80,'='))
print('shape屬性:',df.shape)
print('我是分割線'.center(80,'='))
print('size屬性:',df.size)
-------------------------------------------------------------------------------------
index屬性:  DatetimeIndex(['2018-09-01', '2018-09-02', '2018-09-03', '2018-09-04',
               '2018-09-05', '2018-09-06', '2018-09-07', '2018-09-08'],
              dtype='datetime64[ns]', freq='D')
=====================================我是分割線======================================
columns屬性: Index(['A', 'B', 'C', 'D', 'E'], dtype='object')
=====================================我是分割線======================================
values屬性: [[9 9 4 8 8]
 [1 5 3 6 3]
 [3 3 2 1 9]
 [5 1 7 3 5]
 [2 6 4 5 5]
 [4 8 2 2 8]
 [8 1 3 4 3]
 [6 9 2 1 8]]
=====================================我是分割線======================================
dtypes屬性 A    int32
B    int32
C    int32
D    int32
E    int32
dtype: object
=====================================我是分割線======================================
ndim屬性: 2
=====================================我是分割線======================================
shape屬性: (8, 5)
=====================================我是分割線======================================
size屬性: 40

Series

Series是一維,可以理解為加強版的一維array.

Series的可以由like-array,dict,scalar(標量)等多種形式建立,原則是index的長度與data的長度一致

1.從like-array建立:

pd.Series(np.random.randint(1,10,4),index=list('abcd'))
Out[4]: 
a    7
b    1
c    4
d    4
dtype: int32

pd.Series([1,2,3],index=['A','B','C'])
Out[5]: 
A    1
B    2
C    3
dtype: int64

2,從dict建立,此方式若不指定index則預設為dict的key,若指定則使用指定的index,若有index中沒有的key,則values用NaN代替

pd.Series({'b' : 1, 'a' : 0, 'c' : 2})
Out[7]: 
a    0
b    1
c    2
dtype: int64

pd.Series({'b' : 1, 'a' : 0, 'c' : 2},index=list('abK'))
Out[8]: 
a    0.0
b    1.0
K    NaN
dtype: float64

3. 使用標量建立Series,但該方式必須指定index

pd.Series(5,index=list('abc'))
Out[9]: 
a    5
b    5
c    5
dtype: int64

Series既然是'array'的加強版,自然是like-array的型別,Series物件適用array的大部分Ufinc,以及切片索引的方式.

s=pd.Series(np.random.randint(1,10,8),index=list('abcdefgh'))

Out[11]: 
a    7
b    6
c    9
d    9
e    4
f    7
g    9
h    4
dtype: int32

s[0]
Out[12]: 7

s[1:5]
Out[13]: 
b    6
c    9
d    9
e    4
dtype: int32

s[s>8]
Out[15]: 
c    9
d    9
g    9
dtype: int32

s[[0,3,6]]
Out[16]: 
a    7
d    9
g    9
dtype: int32

np.mean(s)
Out[17]: 6.875

Series物件同時也是like-dict型別.也可類似dict一樣取值,判斷.

s['a']
Out[18]: 7

'b' in s
Out[19]: True

s.get('p',np.NaN)
Out[21]: nan

Series物件同樣可以增加和刪除元素

s['pp']=100

s
Out[88]: 
a       6
b       3
c       7
d       3
e       4
f       1
g       8
h       5
pp    100
dtype: int64

del s['pp']

s
Out[90]: 
a    6
b    3
c    7
d    3
e    4
f    1
g    8
h    5
dtype: int64

Series的屬性前文已經有介紹,這裡在提一下name屬性.

Series的name屬性是可以直接修改,也可以重新命名.區別是直接修改name屬性,則是在原物件上修改,而重新命名預設是返回一個新的物件(可以使用引數inplace設定為修改原物件).同時,Series物件的name屬性在建立DaraFrame時可以轉化為column.

s.name='example'

s1=s.rename('s1')

s
Out[25]: 
a    7
b    6
c    9
d    9
e    4
f    7
g    9
h    4
Name: example, dtype: int32

s1
Out[26]: 
a    7
b    6
c    9
d    9
e    4
f    7
g    9
h    4
Name: s1, dtype: int32

最後重點提一下Series物件和ndarray的最重要的區別.

array物件進行向量化操作時,必須是 同形的,既shape屬性一致,否則無法進行向量化運算.

而Series物件則不同,會自動按index進行資料對齊.

arr1=np.array([1,2,3])

arr2=np.array([4,5,6,7])

arr1+arr2
Traceback (most recent call last):

  File "<ipython-input-29-e489ba1ad4d1>", line 1, in <module>
    arr1+arr2

ValueError: operands could not be broadcast together with shapes (3,) (4,) 


s+s1[1:8]
Out[30]: 
a     NaN
b    12.0
c    18.0
d    18.0
e     8.0
f    14.0
g    18.0
h     8.0
dtype: float64

DataFrame

DataFrame的建立方式非常的多,可以由二維的ndarray或者矩陣,字典(各種巢狀字典,比如由元組,列表,Series構成的字典),也可以從另一個DataFrame建立,下面僅介紹幾種常見的方式.

1.由Series構成的字典

d = {'one' : pd.Series([1., 2., 3.], index=['a', 'b', 'c']),  'two' : pd.Series([1., 2., 3., 4.], index=['a', 'b', 'c', 'd'])}
     

pd.DataFrame(d)
Out[74]: 
   one  two
a  1.0  1.0
b  2.0  2.0
c  3.0  3.0
d  NaN  4.0

 如果不另行指定index和columns則按原有的取並集,缺失元素自動填充為NaN

同樣,可以指定index和colmuns, 但是按照取交集的原則

pd.DataFrame(d, index=['d', 'b', 'a'], columns=['two', 'three'])
Out[75]: 
   two three
d  4.0   NaN
b  2.0   NaN
a  1.0   NaN

2.由列表構成的字典建立DataFrame

d = {'one' : [1., 2., 3., 4.],  'two' : [4., 3., 2., 1.]}

pd.DataFrame(d, index=['a', 'b', 'c', 'd'])
Out[43]: 
   one  two
a  1.0  4.0
b  2.0  3.0
c  3.0  2.0
d  4.0  1.0

3.由巢狀字典建立

pop={'Nevada':{2001:2.4,2002:2.9},'Ohio':{2001:1.6,2002:3.0,2003:3.4}}

pd.DataFrame(pop)
Out[79]: 
      Nevada  Ohio
2001     2.4   1.6
2002     2.9   3.0
2003     NaN   3.4

DataFrame物件的選取,增加,刪除.

df=pd.DataFrame.from_dict(dict([('A', [1, 2, 3]), ('B', [4, 5, 6])]))

df
Out[92]: 
   A  B
0  1  4
1  2  5
2  3  6

DataFrame物件的列的選取,類似於字典操作,直接按照列名取值即可,同樣也可以支援dict的get 方法

 df['A']
Out[95]: 
0    1
1    2
2    3
Name: A, dtype: int64

df.get('C','None')
Out[96]: 'None'

DataFrame物件的列增加,則有一個index對齊的原則,如果是標量,則會自動廣播至所有行,若無index的話,長度必須與列的長度一致,若有index的話,則按index對齊,無法對齊的填充NaN值.

df['C']=10

df['D']=pd.Series([7,8,9])

df['E']=[10,11,12]

df
Out[100]: 
   A  B   C  D   E
0  1  4  10  7  10
1  2  5  10  8  11
2  3  6  10  9  12

預設情況下,新新增的列都是位於最後的,可以通過insert函式指定新增的位置

df.insert(0,'K',100)

df
Out[102]: 
     K  A  B   C  D   E
0  100  1  4  10  7  10
1  100  2  5  10  8  11
2  100  3  6  10  9  12

除了使用類字典的方式增加列,還可以使用assign函式來增加列,並且可以按照指定表示式新增列的值

df.assign(M=df['A']+df['B'])
Out[103]: 
     K  A  B   C  D   E  M
0  100  1  4  10  7  10  5
1  100  2  5  10  8  11  7
2  100  3  6  10  9  12  9

使用del 關鍵字就可以刪除指定的列元素

del df['K']

df
Out[105]: 
   A  B   C  D   E
0  1  4  10  7  10
1  2  5  10  8  11
2  3  6  10  9  12

DataFrame物件行元素的選取,增加,刪除.

類字典的方式,在列選取的時候需要的是列的名稱,而行選取的時,需要的時類切片的方式

f[:1]
Out[107]: 
   A  B   C  D   E
0  1  4  10  7  10

df[1:3]
Out[108]: 
   A  B   C  D   E
1  2  5  10  8  11
2  3  6  10  9  12

同時還提供了loc和iloc 兩個方法,loc需要index作為參賽,iloc需要的是index_number作為參賽

df.index=['First','Secend','Three']

df
Out[117]: 
        A  B   C  D   E
First   1  4  10  7  10
Secend  2  5  10  8  11
Three   3  6  10  9  12

df.loc['First']
Out[118]: 
A     1
B     4
C    10
D     7
E    10
Name: First, dtype: int64

df.iloc[0]
Out[119]: 
A     1
B     4
C    10
D     7
E    10
Name: First, dtype: int64

增加行元素(同樣也可以使用iloc)

df.loc['Four']=[1,2,3,4,5]

df
Out[124]: 
        A  B   C  D   E
First   1  4  10  7  10
Secend  2  5  10  8  11
Three   3  6  10  9  12
Four    1  2   3  4   5

刪除行的話,就只能使用drop方法了(inplace指定是否修改原資料)

df.drop('First',axis=0)
Out[130]: 
        A  B   C  D   E
Secend  2  5  10  8  11
Three   3  6  10  9  12
Four    1  2   3  4   5

該方法並不直接修改原資料,而是返回新的物件,可以通過inplace引數指定是否對在原資料修改,同時指定axis=1也可以刪除列

df.drop('E',axis=1)
Out[132]: 
        A  B   C  D
First   1  4  10  7
Secend  2  5  10  8
Three   3  6  10  9
Four    1  2   3  4

DataFrame物件具體某一個元素的定位

有了行列的選取方法後,就可以直接對某一個指定元素進行定位了.也可以直接給元素賦值.

df[:1]['A']
Out[148]: 
First    1
Name: A, dtype: int64

df.loc['Four','A']
Out[153]: 1

df.iloc[3,0]=1000

df.iloc[3,0]
Out[155]: 1000

小結

 本章主要介紹了Pandas中的最重要的兩個資料結構型別,Series和DataFrame.

 理解以下最要的兩點非常重要:

1.index的自動對齊性(包括在各種運算中)

2.原資料物件的不可變更性,特別是大多數的方法返回的都是一個新的物件,而不是在原資料上進行操作.