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.原資料物件的不可變更性,特別是大多數的方法返回的都是一個新的物件,而不是在原資料上進行操作.