數據分析篇(六)
- 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())