數據分析篇(六)

  • 2019 年 10 月 6 日
  • 筆記

數據合併

join:默認情況是把行索引相同的數據合併到一起

實例:

import pandas as pd

import numpy as np

attr1 = pd.DataFrame(np.arange(12).reshape(3,4),index=list('ABC'),columns=list('abcd'))

attr2 = pd.DataFrame(np.arange(100,106).reshape(2,3),index=list('AB'),columns=list('qwe'))

attr = attr1.join(attr2)

print(attr)

輸出:

a b c d q w e

A 0 1 2 3 100.0 101.0 102.0

B 4 5 6 7 103.0 104.0 105.0

C 8 9 10 11 NaN NaN NaN

# 以attr1為主,合併行相同的,不存在就以NaN填充。

# 如果是attr2.join(attr1) 就會以attr2為主。

# 注意:在合併行的時候,列的索引是不能夠相同的

merge:通過並列合併

# 這裡的merge可以達到和我們數據左連接,右鏈接,內鏈接相同的效果。

實例:

attr3 = pd.DataFrame(np.arange(1,13).reshape(3,4),columns=list('aqwe'))

attr4 = pd.DataFrame(np.ones((3,4)),index=list('ABC'),columns=list('abcd'))

attr = attr3.merge(attr4,on='a')

print(attr)

輸出:

a q w e b c d

0 1 2 3 4 1.0 1.0 1.0

1 1 2 3 4 1.0 1.0 1.0

2 1 2 3 4 1.0 1.0 1.0

# 參數on表示通過那一列去合併,同時還是以attr3為主

# 在默認情況下,是內鏈接,也就是取交集

# 取的值是attr3和attr4中a相同的數字的行

# 由於這裡的attr4中全是1,所以把attr4中全取出來了,attr3中只取了是1的那一行。

# 內鏈接完整的想法:attr = attr3.merge(attr4,on='a',how='inner'),和並的方式用how參數

外鏈接(取並集):

attr = attr3.merge(attr4,on='a',how='outer')

輸出結果:

a q w e b c d

0 1 2 3 4 1.0 1.0 1.0

1 1 2 3 4 1.0 1.0 1.0

2 1 2 3 4 1.0 1.0 1.0

3 5 6 7 8 NaN NaN NaN

4 9 10 11 12 NaN NaN NaN

左鏈接

attr = attr3.merge(attr4,on='a',how='left')

輸出和外連接一樣,之所以一樣,是因為我們的數據

右鏈接

輸出結果:

a q w e b c d

0 1 2 3 4 1.0 1.0 1.0

1 1 2 3 4 1.0 1.0 1.0

2 1 2 3 4 1.0 1.0 1.0

# 數據不全會用NaN補全。

分組聚合

groupby:分組

dict = {'name':['張三','李四','王五'],'age':[18,20,27],'tel':[10010,10086,1008611],'sex':['男','女','男']}

attr1 = pd.DataFrame(dict)

# 按照性別分組

attr = attr1.groupby(by='sex')

print(attr) # DataFrameGroupBy類型

# 需要遍歷輸出

for i,item in attr:

print(i)

print('——')

print(item)

輸出:

——

name age tel sex

1 李四 20 10086 女

——

name age tel sex

0 張三 18 10010 男

2 王五 27 1008611 男

# 按照性別將男女分開。

如果只想取性別為男的數據:

attr1[attr1['sex']=='男']

# 分組是可以根據多個字段分組的,號隔開即可。

聚合函數

count():

實例:

sex_by_count = attr.count()

print(sex_by_count )

輸出:

name age tel

sex

女 1 1 1

男 2 2 2

也就是計算了根據分組後每個組的數量。

sum:非NaN的和

mean:非NaN的平均值

median:非NaN的的算術中位數

std,var : 標準差和方差

min,max:非NaN的的最小值和最大值

索引的方法和屬性

index:

實例:

print(sex_by_count.index)

輸出:

Index(['女', '男'], dtype='object', name='sex')

改變索引:

sex_by_count.index = list('ab')

或者:

sex_by_count.index = ['a','b']

print(sex_by_count.index)

變成:

name age tel

a 1 1 1

b 2 2 2

將索引替換成了a,b

reindex:

print(sex_by_count.reindex(list('ac')))

輸出:

name age tel

a 1.0 1.0 1.0

c NaN NaN NaN

當存在索引為a的行,輸出,不存在輸出NaN填充

指定某一列為索引

# 指定name為索引值

print(sex_by_count.set_index("name"))

輸出:

age tel

name

1 1 1

2 2 2

# 會發現name值作為索引後,後面就沒有值了,我們想讓他顯示:

sex_by_count.set_index("name",drop=False)

輸出:

name age tel

name

1 1 1 1

2 2 2 2

當我們用name做索引的時候,那麼索引中存在相同的值是不合理的。

# 查看某列不相同的數量;

sex_by_count.unique()

# 去重複

sex_by_count.set_index("name").index.unique()

# 設置多個索引值

sex_by_count.set_index(["name",'age'],drop=False)

# 當我們有多個索引的時候,怎麼操作?

複合索引

實例:

dict = {'name':['張三','李四','王五'],'age':[18,20,27],'tel':[10010,10086,1008611],'sex':['男','女','男']}

attr1 = pd.DataFrame(dict)

# 設置sex和name為索引值

attr2 = attr1.set_index(["sex","name"])

# 取性別為男的張三的年齡

attr3 = attr2['age']

print(attr3['男']['張三'])

# 取性別為男的人的數據

print(attr3['男'])

# 但是如果我們交換索引位置

attr4 = attr1.set_index(["name","sex"])

# 此時如果我們還是只想取男生的年齡,用之前的操作就不行了

# 我們需要這樣寫

attr5 = attr4['age']

attr6 = attr5.swaplevel()

print(attr6['男'])

# 如果我們用loc取值

attr3.loc['男'].loc['張三']

處理時間

自動生成時間:

實例:

attr = pd.date_range(start='20170101',end='20180101',freq='D')

print(attr)

輸出:

DatetimeIndex(['2017-01-01', '2017-01-02', '2017-01-03', '2017-01-04',

'2017-01-05', '2017-01-06', '2017-01-07', '2017-01-08',

'2017-01-09', '2017-01-10',

'2017-12-23', '2017-12-24', '2017-12-25', '2017-12-26',

'2017-12-27', '2017-12-28', '2017-12-29', '2017-12-30',

'2017-12-31', '2018-01-01'],

dtype='datetime64[ns]', length=366, freq='D')

# atart 開始時間, end結束時間,freq : D是以天為單位,10D就是以10天為單位,M就是月等等

其他:

B:工作日

H:小時

T或min:分

S:秒

L或ms:毫秒

U:微妙

BM:每月最後一個工作日

MS:每月第一天

BMS:每月第一個工作日

# 時間是可以作為索引的

# 以20天為一個間隔

attr = pd.date_range(start='20170101',end='20180101',freq='20D')

輸出:

DatetimeIndex(['2017-01-01', '2017-01-21', '2017-02-10', '2017-03-02',

'2017-03-22', '2017-04-11', '2017-05-01', '2017-05-21',

'2017-06-10', '2017-06-30', '2017-07-20', '2017-08-09',

'2017-08-29', '2017-09-18', '2017-10-08', '2017-10-28',

'2017-11-17', '2017-12-07', '2017-12-27'],

dtype='datetime64[ns]', freq='20D')

# 輸出前10個 不能有結束時間

attr = pd.date_range(start='20170101',periods=10,freq='20D')

# 將字符串轉化為時間

pd.to_datetime(時間列,format='')

# format 是格式化,常用的格式符號請看基礎篇中的time模塊。

pandas重採樣

重採樣:指將時間序列從一個頻率轉化為另一個頻率的過程。

降採樣:高頻率轉化為低頻率(比如將一個精確到秒的時間轉化為只有年月日)

升採樣:低頻率轉化為高頻率(與上面相反)

我們需要用resample來實現頻率轉換。

比如:

# 生成100行數據,索引為100個從2017-01-01開始每一個加一個小時,並且精確到秒

attr = pd.DataFrame(np.arange(100).reshape((100,1)),index=pd.date_range(start='20170101',periods=100,freq='3600S'))

# 降採樣

attr1 = attr.resample('D')

# 取每天的平均值。

print(attr1.mean())

Exit mobile version