pandas數據大發888平臺出租規整化:清理、轉換、合並、重塑
許多人選擇使用通用編程語言或unix文本處理工具(如sed或awk)對數據格式進行專門處理。
幸運的是,pandas和python標準庫提供了一組高級的、靈活的、高效的核心函數和算法,將數據規整化正確的形式。
- 合並數據集:
pandas對象中的數據可以通過一些內置的方式進行合並:
(1)pandas.merge可根據一個名多個鍵將不同DataFrame中的行連接起來。sql關系型數據庫也有merge法,它是用merge實現的就是數據庫的連接操作(inner內連接交集,outer外連接,左連接,右連接=>並集)。
(3)實例方法combine_first可以將重復數據編接在一起,用一個對象中的值填充另一個對象中的缺失值。
下面分別講解這些方法:
數據庫風格的DataFrame合並:
數據集的合並(merge)或連接(join)運算是通過一個或多個鍵將行連接起來的。這些運算是關系型數據庫的核心。
pandas的merge函數是對數據應用這些算法的主要切入點。
(1)merge的用法
import pandas as pd import numpy as np from pandas import Series,DataFrame df1=DataFrame({‘key‘:[‘b‘,‘b‘,‘a‘,‘c‘,‘a‘,‘a‘,‘b‘], ‘data1‘:range(7)}) df2=DataFrame({‘key‘:[‘a‘,‘b‘,‘d‘], ‘data2‘:range(3)}) print df1 #輸出結果如下: # data1 key # 0 0 b # 1 1 b # 2 2 a # 3 3 c # 4 4 a # 5 5 a # 6 6 b # print df2 # #輸出結果如下: # data2 key # 0 0 a # 1 1 b # 2 2 d (1)這是一種多對一的合並:df1中的數據有多個被標記為a和b行,而df2中key列的每個值則僅對應一行。 這些對象調用merge即可得到 print pd.merge(df1,df2) #輸出結果如下: # data1 key data2 # 0 0 b 1 # 1 1 b 1 # 2 6 b 1 # 3 2 a 0 # 4 4 a 0 # 5 5 a 0 # #註意:上面的例子並沒有指明要用哪個列進行連接。如果沒有指定,merge就會將重疊列的列名當做鍵。 (2)下面指定列:用能數on= # print pd.merge(df1,df2,on=‘key‘) #輸出結果與上面一樣 (3)如果兩個對象的列名不同,也可以分別進行指定:left_on,right_on df3=DataFrame({‘lkey‘:[‘b‘,‘b‘,‘a‘,‘c‘,‘a‘,‘a‘,‘b‘], ‘data1‘:range(7)}) df4=DataFrame({‘rkey‘:[‘a‘,‘b‘,‘d‘], ‘data2‘:range(3)}) print pd.merge(df3,df4,left_on=‘lkey‘,right_on=‘rkey‘) #輸出結果如下: # data1 lkey data2 rkey # 0 0 b 1 b # 1 1 b 1 b # 2 6 b 1 b # 3 2 a 0 a # 4 4 a 0 a # 5 5 a 0 a # #註意:結果裏面c和d以及與之相關的數據消失了。默認情況下,merge做的是"inner"連接:結果中的鍵是交集。 # 而其它外連接left,right,outer求取的是鍵的並集,組合了左連接和右連接的效果。 (4) outer外連接:並集,兩個數據Key都要 # print pd.merge(df1,df2,how=‘outer‘) #外連接,兩邊的key都要傳入 # #輸出結果如下:並集,df1,df2所有的值都放入 # # data1 key data2 # # 0 0.0 b 1.0 # # 1 1.0 b 1.0 # # 2 6.0 b 1.0 # # 3 2.0 a 0.0 # # 4 4.0 a 0.0 # # 5 5.0 a 0.0 # # 6 3.0 c NaN # # 7 NaN d 2.0 (5) left左連接:並集,左連接是以左邊的為主 # print pd.merge(df1,df2,on=‘key‘,how=‘left‘) #左連接 # #輸出結果如下: 左連接是以左邊的為主,即df1為主,顧只有df1的key # # data1 key data2 # # 0 0 b 1.0 # # 1 1 b 1.0 # # 2 2 a 0.0 # # 3 3 c NaN # # 4 4 a 0.0 # # 5 5 a 0.0 # # 6 6 b 1.0 (6)right右連接:並集,右連接是以右邊的為主 # print pd.merge(df1,df2,how=‘right‘) #右連接 # #輸出結果如下:右連接,以df2的為主,顧只有df2的key,其它的值是全部寫入 # # data1 key data2 # # 0 0.0 b 1 # # 1 1.0 b 1 # # 2 6.0 b 1 # # 3 2.0 a 0 # # 4 4.0 a 0 # # 5 5.0 a 0 # # 6 NaN d 2 (7)inner內連接:交集,默認就是內連接 # print pd.merge(df1,df2,how=‘inner‘) #即merge默認情況下是inner,inner是交集 # #輸出結果如下:取df1,df2都有key # # data1 key data2 # # 0 0 b 1 # # 1 1 b 1 # # 2 6 b 1 # # 3 2 a 0 # # 4 4 a 0 # # 5 5 a 0 (8)若多個鍵要進行合並,傳入一個由列名組成的列表即可 left=DataFrame({‘key1‘:[‘foo‘,‘foo‘,‘bar‘], ‘key2‘:[‘one‘,‘two‘,‘one‘], ‘lval‘:[1,2,3]}) right=DataFrame({‘key1‘:[‘foo‘,‘foo‘,‘bar‘,‘bar‘], ‘key2‘:[‘one‘,‘one‘,‘one‘,‘two‘], ‘rval‘:[4,5,6,7]}) print left #輸出結果如下: # key1 key2 lval # 0 foo one 1 # 1 foo two 2 # 2 bar one 3 print right #輸出結果如下: # key1 key2 rval # 0 foo one 4 # 1 foo one 5 # 2 bar one 6 # 3 bar two 7 print pd.merge(left,right,on=[‘key1‘,‘key2‘],how=‘outer‘) #輸出結果如下:看key1,key2兩個鍵對應的lval的值。外連接,即所有的key都要。 #right中的key組合[foo,one],[foo,one],[foo,two]...用right的key看left有沒有。 # key1 key2 lval rval # 0 foo one 1.0 4.0 # 1 foo one 1.0 5.0 # 2 foo two 2.0 NaN # 3 bar one 3.0 6.0 # 4 bar two NaN 7.0 (9)合並運算需要考慮對重復列名的處理,merge有一個實用的suffixes選項,用於指定附加到左右兩個DataFrame對象的重疊列名上的字符串。 print pd.merge(left,right,on=‘key1‘) #只用單個key,它就有單個key1分別和left,right的key2的組合 #輸出結果如下: # key1 key2_x lval key2_y rval # 0 foo one 1 one 4 # 1 foo one 1 one 5 # 2 foo two 2 one 4 # 3 foo two 2 one 5 # 4 bar one 3 one 6 # 5 bar one 3 two 7 print pd.merge(left,right,on=‘key1‘,suffixes=(‘_left‘,‘_right‘)) #輸出結果如下: # key1 key2_left lval key2_right rval # 0 foo one 1 one 4 # 1 foo one 1 one 5 # 2 foo two 2 one 4 # 3 foo two 2 one 5 # 4 bar one 3 one 6 # 5 bar one 3 two 7
merger函數的參數
參數 說明
left 參與合並的左側DataFrame
right 參與合並的右側DataFrame
how “inner”、“outer”、“left”、“right”其中之一。默認為"inner"(交集),其它為並集
on 用於連接的列名。必須存在於左右兩個DataFrame對象中。如果未指定,且其它連接鍵也未指定,由以
left和right列名的交集作為連接鍵
left_on 左側DataFrame中用作連接鍵的列
right_on 右側DataFrame中用作連接鍵的列
left_index 將左側的行索引用作其連接鍵
righgt_index 將右側的行索引用作其連接鍵
suffixes 字符串值元組,用於追加到重疊列名的末尾,默認為(‘_x‘,‘_y‘).
copy 設置為False,可以在某些特殊情況下避免將數據復制到結果數據結構中。默認總是復制。
索引上DataFrame的合並:
DataFrame中的連接鍵位於其索引中。在這種情況下,可以傳入left_index=True或right_index=True(或兩個都傳)
以說明索引應該被用作連接鍵。
(1)merge的用法:索引上合並用left_index=True、right_index=True
import pandas as pd
import numpy as np
from pandas import Series,DataFrame
(1)DataFrame中的連接鍵位於其索引中:left_index=True或right_index=True(或兩個都傳)來說明索引應該被用作連接鍵。
left1=DataFrame({‘key‘:[‘a‘,‘b‘,‘a‘,‘a‘,‘b‘,‘c‘],
‘value‘:range(6)})
right1=DataFrame({‘group_val‘:[3.5,7]},index=[‘a‘,‘b‘])
print left1
#輸出結果如下:
# key value
# 0 a 0
# 1 b 1
# 2 a 2
# 3 a 3
# 4 b 4
# 5 c 5
print right1
#輸出結果如下:
# group_val
# a 3.5
# b 7.0
print pd.merge(left1,right1,left_on=‘key‘,right_index=True)
#輸出結果如下:
# key value group_val
# 0 a 0 3.5
# 2 a 2 3.5
# 3 a 3 3.5
# 1 b 1 7.0
# 4 b 4 7.0
(2)由於默認的merge方法是求取連接鍵的交集,因此可以通過外連接的方式得到它們的並集。how=‘outer‘
print pd.merge(left1,right1,left_on=‘key‘,right_index=True,how=‘outer‘)
#輸出結果如下:
# key value group_val
# 0 a 0 3.5
# 2 a 2 3.5
# 3 a 3 3.5
# 1 b 1 7.0
# 4 b 4 7.0
# 5 c 5 NaN
(3)層次化索引,多層行/列索引
lefth=DataFrame({‘key1‘:[‘Ohio‘,‘Ohio‘,‘Ohio‘,‘Nevada‘,‘Nevada‘],
‘key2‘:[2000,2001,2002,2001,2002],
‘data‘:np.arange(5.)})
righth=DataFrame(np.arange(12).reshape(6,2),
index=[[‘Nevada‘,‘Nevada‘,‘Ohio‘,‘Ohio‘,‘Ohio‘,‘Ohio‘],
[2001,2000,2000,2000,2001,2002]],
columns=[‘event1‘,‘event2‘])
print lefth
#輸出結果如下:
# data key1 key2
# 0 0.0 Ohio 2000
# 1 1.0 Ohio 2001
# 2 2.0 Ohio 2002
# 3 3.0 Nevada 2001
# 4 4.0 Nevada 2002
print righth
#輸出結果如下:
# event1 event2
# Nevada 2001 0 1
# 2000 2 3
# Ohio 2000 4 5
# 2000 6 7
# 2001 8 9
# 2002 10 11
#必須以列表的形式指明用作合並鍵的多個列(註意對重復索引值的處理)
#left_on左側DataFrame作為連接鍵,即lefth,而索引是right_index,即右側數據為行索引即righth的行索引為行索引
print pd.merge(lefth,righth,left_on=[‘key1‘,‘key2‘],right_index=True)
#沒有how參數,默認是inner連接,即交集,取lefth的[‘key1‘,‘key2‘]的數據與righth的行有交集,即相同的取出
#輸出結果如下:
# data key1 key2 event1 event2
# 0 0.0 Ohio 2000 4 5
# 0 0.0 Ohio 2000 6 7
# 1 1.0 Ohio 2001 8 9
# 2 2.0 Ohio 2002 10 11
# 3 3.0 Nevada 2001 0 1
#(4)外連接:how=‘outer‘ 並集
print pd.merge(lefth,righth,left_on=[‘key1‘,‘key2‘],right_index=True,how=‘outer‘)
#輸出結果如下:
# data key1 key2 event1 event2
# 0 0.0 Ohio 2000 4.0 5.0
# 0 0.0 Ohio 2000 6.0 7.0
# 1 1.0 Ohio 2001 8.0 9.0
# 2 2.0 Ohio 2002 10.0 11.0
# 3 3.0 Nevada 2001 0.0 1.0
# 4 4.0 Nevada 2002 NaN NaN
# 4 NaN Nevada 2000 2.0 3.0
#(5)用merge同時使用合並雙方的索引
left2=DataFrame([[1.,2.],[3.,4.],[5.,6.]],index=[‘a‘,‘c‘,‘e‘],
columns=[‘Ohio‘,‘Nevada‘])
right2=DataFrame([[7.,8.],[9.,10.],[11.,12.],[13,14]],
index=[‘b‘,‘c‘,‘d‘,‘e‘],columns=[‘Missouri‘,‘Alabama‘])
print left2
#輸出結果如下:
# Ohio Nevada
# a 1.0 2.0
# c 3.0 4.0
# e 5.0 6.0
print right2
#輸出結果如下:
# Missouri Alabama
# b 7.0 8.0
# c 9.0 10.0
# d 11.0 12.0
# e 13.0 14.0
print pd.merge(left2,right2,how=‘outer‘,left_index=True,right_index=True)
#同時使用了left_index,right_index同時合並雙方索引,且outer外連接交集
#輸出結果如下:
# Ohio Nevada Missouri Alabama
# a 1.0 2.0 NaN NaN
# b NaN NaN 7.0 8.0
# c 3.0 4.0 9.0 10.0
# d NaN NaN 11.0 12.0
# e 5.0 6.0 13.0 14.0
(2)join的用法:索引上合並用left_index=True、right_index=True
DataFrame的一個實例方法Join:更為方便地實現按索引合並。它還可以用於合並多個帶有相同或相似索引的DataFrame對象,而不管它們之間有沒有重疊的列。
#Join:在連接鍵上是做左連接
# (1)DataFrame的一個實例方法Join:更為方便地實現按索引合並。不管它們之間有沒有重疊的列。
#上面的例子可以編寫如下:
print left2.join(right2,how=‘outer‘) #類似python的字符串連接Join
#輸出結果如下:
# Ohio Nevada Missouri Alabama
# a 1.0 2.0 NaN NaN
# b NaN NaN 7.0 8.0
# c 3.0 4.0 9.0 10.0
# d NaN NaN 11.0 12.0
# e 5.0 6.0 13.0 14.0
# (2)它還支持DataFrame的索引跟調用者DataFrame的某個列之間的連接(即第一個DataFrame的行索引與第二個DataFrame的列連接)
print left1.join(right1,on=‘key‘)
#輸出結果如下:
# key value group_val
# 0 a 0 3.5
# 1 b 1 7.0
# 2 a 2 3.5
# 3 a 3 3.5
# 4 b 4 7.0
# 5 c 5 NaN
#(3)可以向join傳入一組DataFrame
another=DataFrame([[7.,8.],[9.,10.],[11.,12.],[16.,17.]],
index=[‘a‘,‘c‘,‘e‘,‘f‘],columns=[‘New York‘,‘Oregon‘])
print another
#輸出結果如下:
# New York Oregon
# a 7.0 8.0
# c 9.0 10.0
# e 11.0 12.0
# f 16.0 17.0
print left2.join([right2,another]) #left2左分別連接right2,another
# left2內容如下:
# # Ohio Nevada
# # a 1.0 2.0
# # c 3.0 4.0
# # e 5.0 6.0
# right2內容如下:
# # Missouri Alabama
# # b 7.0 8.0
# # c 9.0 10.0
# # d 11.0 12.0
# # e 13.0 14.0
#left2.join([right2,another])輸出結果如下:
# Ohio Nevada Missouri Alabama New York Oregon
# a 1.0 2.0 NaN NaN 7.0 8.0
# c 3.0 4.0 9.0 10.0 9.0 10.0
# e 5.0 6.0 13.0 14.0 11.0 12.0
軸上連接:
另一種數據合並運算也被稱作連接、綁定或堆疊。numpy有一個用於合並原始Numpy數組的concatenation函數。concatenate是Numpy的方法,
而concate是pandas的方法。
concatenate連接:
arr=np.arange(12).reshape((3,4))
print arr
#輸出的結果如下:
# [[ 0 1 2 3]
# [ 4 5 6 7]
# [ 8 9 10 11]]
print np.concatenate([arr,arr],axis=1) #axis=1是列
#輸出的結果如下:
# [[ 0 1 2 3 0 1 2 3]
# [ 4 5 6 7 4 5 6 7]
# [ 8 9 10 11 8 9 10 11]]
concate連接:
# 如果各對象其他軸上的索引不同,那些軸應該是做並集還是交集?
# 結果對象中的分組需要各不相同嗎?
# 用於連接的軸axis重要嗎?
concate用於解決上面的三個問題,它與concatenate沒多大區別,只是多了一些參數
(1)三個沒有重疊索引的Series,對這些對象調用concat可以將值和索引粘合在一起
s1=Series([0,1],index=[‘a‘,‘b‘])
s2=Series([2,3,4],index=[‘c‘,‘d‘,‘e‘])
s3=Series([5,6],index=[‘f‘,‘g‘])
print s1
# a 0
# b 1
print s2
# c 2
# d 3
# e 4
print s3
# f 5
# g 6
print pd.concat([s1,s2,s3])
#輸出結果如下:
# a 0
# b 1
# c 2
# d 3
# e 4
# f 5
# g 6
(2)默認情況下,concat是在axix=0行上作用的,最終產生一個新的Series.如果傳入axis=1,則結果就會變成一個DataFrame(axis=1是列)
#series行向合並,本來series只有行索引,故產生一個新的Series.如果列合並,有幾個數組,列不一定相同,所以會產生一個DataFrame
print pd.concat([s1,s2,s3],axis=1)
#輸出結果如下:
# 0 1 2
# a 0.0 NaN NaN
# b 1.0 NaN NaN
# c NaN 2.0 NaN
# d NaN 3.0 NaN
# e NaN 4.0 NaN
# f NaN NaN 5.0
# g NaN NaN 6.0
(3)這種情況下,另外一條軸上沒有重疊,從索引的有序並集上就可以看出。。傳入join=‘inner‘即可得到它們的交集
s4=pd.concat([s1*5,s3])
print pd.concat([s1,s4],axis=1)
#輸出結果如下:
# 0 1
# a 0.0 0
# b 1.0 5
# f NaN 5
# g NaN 6
print pd.concat([s1,s4],axis=1,join=‘inner‘)
#輸出結果如下:
# 0 1
# a 0 0
# b 1 5
(4)可以通過join_axes指字要在其他軸上使用的索引
print pd.concat([s1,s4],axis=1,join_axes=[[‘a‘,‘c‘,‘b‘,‘e‘]])
#輸出結果如下:
# 0 1
# a 0.0 0.0
# c NaN NaN
# b 1.0 5.0
# e NaN NaN
(5)不過有個問題,參與連接的片段在結果中區分不開。假設你想要在連接軸上創建一個層次化索引。使用keys參數即可達到目的
result=pd.concat([s1,s1,s3],keys=[‘one‘,‘two‘,‘three‘])
print result
#輸出結果如下:
# one a 0
# b 1
# two a 0
# b 1
# three f 5
# g 6
# dtype: int64
print result.unstack()
#輸出結果如下:
# a b f g
# one 0.0 1.0 NaN NaN
# two 0.0 1.0 NaN NaN
# three NaN NaN 5.0 6.0
(6)如果沿著axis=1對Series進行合並,則keys就會成為DataFrame的列頭
print pd.concat([s1,s2,s3],axis=1,keys=[‘one‘,‘two‘,‘three‘])
#輸出結果如下:
# one two three
# a 0.0 NaN NaN
# b 1.0 NaN NaN
# c NaN 2.0 NaN
# d NaN 3.0 NaN
# e NaN 4.0 NaN
# f NaN NaN 5.0
# g NaN NaN 6.0
(7)同樣的邏輯對DataFrame對象也是一樣:
df1=DataFrame(np.arange(6).reshape(3,2),index=[‘a‘,‘b‘,‘c‘],
columns=[‘one‘,‘two‘])
df2=DataFrame(5+np.arange(4).reshape(2,2),index=[‘a‘,‘c‘],
columns=[‘three‘,‘four‘])
print pd.concat([df1,df2],axis=1,keys=[‘level1‘,‘level2‘])
#輸出結果如下:
# level1 level2
# one two three four
# a 0 1 5.0 6.0
# b 2 3 NaN NaN
# c 4 5 7.0 8.0
(8)如果傳入的不是列表而是一個字典,則字黃的鍵就會被做Keys選項的值。
print pd.concat({‘level1‘:df1,‘level2‘:df2},axis=1)
# level1 level2
# one two three four
# a 0 1 5.0 6.0
# b 2 3 NaN NaN
# c 4 5 7.0 8.0
(9)此外還有兩個用於管理層次化索引創建方式的參數:
a:key,names
print pd.concat([df1,df2],axis=1,keys=[‘level1‘,‘level2‘],
names=[‘upper‘,‘lower‘])
#輸出的結果如下:
# upper level1 level2
# lower one two three four
# a 0 1 5.0 6.0
# b 2 3 NaN NaN
# c 4 5 7.0 8.0
b:ignore_index=True
df1=DataFrame(np.random.randn(3,4),columns=[‘a‘,‘b‘,‘c‘,‘d‘])
df2=DataFrame(np.random.randn(2,3),columns=[‘b‘,‘d‘,‘a‘])
print df1
print df2
#在這種情況下,傳入ignore_index=True即可:
print pd.concat([df1,df2],ignore_index=True)
#輸出結果如下:
# a b c d
# 0 -0.540071 -0.225394 -0.851317 -1.638987
# 1 0.163700 1.375732 0.255257 1.290061
# 2 0.787074 0.137692 0.929145 -0.793582
# 3 -0.502263 0.717226 NaN -1.224583
# 4 -0.023067 -0.556030 NaN -0.819273
concat函數的參數
參數 說明
objs 參與連接的pandas對象的列表或字典。唯一必需的參數
axis 指明連接的軸向,默認為0
join “inner”、“outer”其中之一,默認為"outer".指明其他軸向上的索引是按交集(inner)
還是並集(outer)進行合並
join_axes 指明用於其他n-1條軸的索引,不執行並集/交集運算
keys 與連接對象有關的值,用於形成連接軸向上的層次化索引。可以是任意值的列表或數組、元組數組、
數組列表(如果將levels設置成多級數組的話)
levels 指定用作層次化索引各級別上的索引,如果設置了keys的話
names 用於創建分層級別的名稱,如果設置了keys和levels的話
verify_integrity 檢查結果對象新軸上的重復情況,如果發現則引發異常。默認(False)允許重復
ignore_index 不保留連接軸上的索引,產生一組新索引
合並重疊數據:numpy.where, pd.combine_first
還有一種數據組合問題不能用簡單的合並(merge)或連接(concatenation)運算來處理。
比如,可能有索引全部或部分重疊的兩個數據集。我們使用Numpy的where函數,它用於表達一種矢量化的if-else:
(1)Numpy的where
import pandas as pd
import numpy as np
from pandas import Series,DataFrame
(1)Numpy的where
a=Series([np.nan,2.5,np.nan,3.5,4.5,np.nan],
index=[‘f‘,‘e‘,‘d‘,‘c‘,‘b‘,‘a‘])
b=Series(np.arange(len(a),dtype=np.float64),
index=[‘f‘,‘e‘,‘d‘,‘c‘,‘b‘,‘a‘])
b[-1]=np.nan
print a
#輸出結果如下:
# f NaN
# e 2.5
# d NaN
# c 3.5
# b 4.5
# a NaN
print b
#輸出結果如下:
# f 0.0
# e 1.0
# d 2.0
# c 3.0
# b 4.0
# a NaN
print np.where(pd.isnull(a),b,a) #a如果是Nan,則用b的數據代替,否則還是a的值
#輸出結果如下:
# [ 0. 2.5 2. 3.5 4.5 nan]
(2)Series有一個combine_first方法,可以實現上面一樣的功能,而且會時行數據對齊
print b[:-2].combine_first(a[2:]) #b[:-2]的值若有nan則用a[2:]的值代替。但是b[:-2]是不包括右邊的倒數第二個b的,
# 則b的值用第一個4.5
#輸出結果如下:
# a NaN
# b 4.5
# c 3.0
# d 2.0
# e 1.0
# f 0.0
#Series的combine_first方法實例:DataFrame也有combine_first方法
s1=pd.Series([1,np.nan])
s2=pd.Series([3,4])
print s1
# 0 1.0
# 1 NaN
print s2
# 0 3
# 1 4
print s1.combine_first(s2) #s1裏有nan就換成s2的值
# 0 1.0
# 1 4.0
(3)DataFrame的combine_first也是同上,因此可以將其看做:用參數對象中的數據為調用者對象的缺失數據"打補丁"
df1=DataFrame({‘a‘:[1.,np.nan,5.,np.nan],
‘b‘:[np.nan,2.,np.nan,6.],
‘c‘:range(2,18,4)})
df2=DataFrame({‘a‘:[5.,4.,np.nan,3.,7.],
‘b‘:[np.nan,3.,4.,6.,8.]})
print df1
#輸出結果如下:
# a b c
# 0 1.0 NaN 2
# 1 NaN 2.0 6
# 2 5.0 NaN 10
# 3 NaN 6.0 14
print df2
#輸出結果如下:
# a b
# 0 5.0 NaN
# 1 4.0 3.0
# 2 NaN 4.0
# 3 3.0 6.0
# 4 7.0 8.0
print df1.combine_first(df2) #用df2裏的數據為df1中的數據為nan的數據打補丁
#輸出結果如下:
# a b c
# 0 1.0 NaN 2.0
# 1 4.0 2.0 6.0
# 2 5.0 4.0 10.0
# 3 3.0 6.0 14.0
# 4 7.0 8.0 NaN
- 重塑和軸向旋轉:
pandas對象中有許多用於重新排列表格型數據的基礎運算。這些函數也稱作重塑或軸向旋轉運算。
(1)stack:將數據的列"旋轉"為行。(將DataFrame轉換成Series,而Series無stack方法)
(2)unstack:與stack相反的操作,將數據的行“旋轉”為列。(將Series轉換成DataFrame,DataFrame還是DataFrame)
重塑層次化索引:
層次化索引為DataFrame數據的重排任務提供了一個具有良好一致性的方式。主要功能有以下二個方法:
層次化索引為DataFrame數據的
stack:將數據的列"旋轉"為行,將DataFrame轉換成Series,Series無stack()方法
unstack:將數據的行"旋轉"為列,將Series轉換成DataFrame了,DataFrame還是DataFrame
(1)將DataFrame的列旋轉為行:DataFrame.stack()
data=DataFrame(np.arange(6).reshape((2,3)),
index=pd.Index([‘Ohio‘,‘Colorado‘],name=‘state‘),
columns=pd.Index([‘one‘,‘two‘,‘three‘],name=‘number‘))
print data
#輸出結果如下:
# number one two three
# state
# Ohio 0 1 2
# Colorado 3 4 5
result=data.stack()
print result
# #輸出結果如下:
# # state number
# # Ohio one 0
# # two 1
# # three 2
# # Colorado one 3
# # two 4
# # three 5
(2)對於一個層次化索引的Series,可以用unstack將其重排為一個DataFrame.
print result.unstack()
#輸出結果如下:
# number one two three
# state
# Ohio 0 1 2
# Colorado 3 4 5
默認情況下,unstack操作的是最內層(stack也是如此)。傳入分層級別的編號或名稱即可對其他級別進行unstack操作
print result.unstack(0)
#輸出結果如下:
# state Ohio Colorado
# number
# one 0 3
# two 1 4
# three 2 5
print result.unstack(‘state‘)
#輸出結果如下:
# state Ohio Colorado
# number
# one 0 3
# two 1 4
# three 2 5
(3)如果不是所有級別值都能在各分組中找到的話,則unstack操作可能會引入缺失數據:
s1=Series([0,1,2,3],index=[‘a‘,‘b‘,‘c‘,‘d‘])
s2=Series([4,5,6],index=[‘c‘,‘d‘,‘e‘])
data2=pd.concat([s1,s2],keys=[‘one‘,‘two‘])
print data2
#輸出結果如下:
# one a 0
# b 1
# c 2
# d 3
# two c 4
# d 5
# e 6
# dtype: int64
print data2.unstack()
#輸出結果如下:
# a b c d e
# one 0.0 1.0 2.0 3.0 NaN
# two NaN NaN 4.0 5.0 6.0
(4)stack默認會濾除缺失數據,因此該運算是可逆的:
# print data2.stack() #報錯‘Series‘ object has no attribute ‘stack‘
#可以對data2.unstack()後的DataFrame進行stack()
print data2.unstack().stack(dropna=False) #DataFrame轉換成Series了,且列變成行了
#輸出結果如下:
# one a 0.0
# b 1.0
# c 2.0
# d 3.0
# e NaN
# two a NaN
# b NaN
# c 4.0
# d 5.0
# e 6.0
print data2.unstack().unstack() #data2.unstack()的行變成列
#輸出結果如下:
# a one 0.0
# two NaN
# b one 1.0
# two NaN
# c one 2.0
# two 4.0
# d one 3.0
# two 5.0
# e one NaN
# two 6.0
(5)對DataFrame進行unstack操作時,作為旋轉軸的級別將會成為結果中的最低級別
df=DataFrame({‘left‘:result,‘right‘:result+5},
columns=pd.Index([‘left‘,‘right‘],name=‘side‘))
print df
#result的內容如下:
# # state number
# # Ohio one 0
# # two 1
# # three 2
# # Colorado one 3
# # two 4
# # three 5
#df的結果如下:
# side left right
# state number
# Ohio one 0 5
# two 1 6
# three 2 7
# Colorado one 3 8
# two 4 9
# three 5 10
print df.unstack(‘state‘) #將state的行旋轉為列
#輸出結果如下:
# side left right
# state Ohio Colorado Ohio Colorado
# number
# one 0 3 5 8
# two 1 4 6 9
# three 2 5 7 10
print df.unstack(‘state‘).stack(‘side‘) #將上面的再stack將列為side的旋轉為行(即left,right)
#輸出結果如下:
# state Colorado Ohio
# number side
# one left 3 0
# right 8 5
# two left 4 1
# right 9 6
# three left 5 2
# right 10 7
將"長格式"轉換為"寬格式":
時間序列數據通常是以所謂的"長格式"(long)或"堆疊格式"(stacked)存儲在數據庫和CSV中的。
關系型數據庫通常是主鍵形式提供了關系的完整性,而且提供了更為簡單的查詢支持。但對於長格式的數據操作起來就不那麽輕松了。
而DataFrame可以把主鍵中不同的Item值分別形成一列,date列中的時間值則用作索引,可以用DataFrame的pivot方法完全可以實現這個轉換。
import pandas as pd
import numpy as np
from pandas import Series,DataFrame
ldata=DataFrame({‘date‘:[‘1959-03-31 00:00:00‘,‘1959-03-31 00:00:00‘,‘1959-03-31 00:00:00‘,
‘1959-06-30 00:00:00‘,‘1959-06-30 00:00:00‘,‘1959-06-30 00:00:00‘,
‘1959-09-30 00:00:00‘,‘1959-09-30 00:00:00‘,‘1959-09-30 00:00:00‘,‘1959-12-31 00:00:00‘],
‘item‘:[‘realgdp‘,‘infl‘,‘unemp‘,‘realgdp‘,‘infl‘,‘unemp‘,‘realgdp‘,‘infl‘,‘unemp‘,‘realgdp‘],
‘value‘:[‘2710.349‘,‘0.000‘,‘5.800‘,‘2778.801‘,‘2.340‘,‘5.100‘,‘2775.488‘,‘2.740‘,‘5.300‘,‘2785.204‘]
})
print ldata
#輸出結果如下:
# date item value
# 0 1959-03-31 00:00:00 realgdp 2710.349
# 1 1959-03-31 00:00:00 infl 0.000
# 2 1959-03-31 00:00:00 unemp 5.800
# 3 1959-06-30 00:00:00 realgdp 2778.801
# 4 1959-06-30 00:00:00 infl 2.340
# 5 1959-06-30 00:00:00 unemp 5.100
# 6 1959-09-30 00:00:00 realgdp 2775.488
# 7 1959-09-30 00:00:00 infl 2.740
# 8 1959-09-30 00:00:00 unemp 5.300
# 9 1959-12-31 00:00:00 realgdp 2785.204
(1)使用DataFrame的pivot的方法
pivoted=ldata.pivot(‘date‘,‘item‘,‘value‘)
print pivoted.head()
#輸出結果如下:
# item infl realgdp unemp
# date
# 1959-03-31 00:00:00 0.000 2710.349 5.800
# 1959-06-30 00:00:00 2.340 2778.801 5.100
# 1959-09-30 00:00:00 2.740 2775.488 5.300
# 1959-12-31 00:00:00 None 2785.204 None
(2)前兩個參數值分別用作行和列索引的列名,最後一個參數值則是用於填充DataFrame的數據列的列名。
#假設有兩個需要參與重塑的數據列:
ldata[‘value2‘]=np.random.randn(len(ldata))
print ldata[:10]
#輸出結果如下:
# date item value value2
# 0 1959-03-31 00:00:00 realgdp 2710.349 0.935557
# 1 1959-03-31 00:00:00 infl 0.000 1.609324
# 2 1959-03-31 00:00:00 unemp 5.800 -0.753734
# 3 1959-06-30 00:00:00 realgdp 2778.801 -0.668879
# 4 1959-06-30 00:00:00 infl 2.340 -0.256601
# 5 1959-06-30 00:00:00 unemp 5.100 0.537770
# 6 1959-09-30 00:00:00 realgdp 2775.488 1.073817
# 7 1959-09-30 00:00:00 infl 2.740 -0.027340
# 8 1959-09-30 00:00:00 unemp 5.300 -0.531161
# 9 1959-12-31 00:00:00 realgdp 2785.204 0.706080
(3)如果忽略掉最後一個參數,得到的DataFrame就會帶有層次化的列
pivoted=ldata.pivot(‘date‘,‘item‘)
print pivoted[:5]
#輸出結果如下:
# value value2
# item infl realgdp unemp infl realgdp unemp
# date
# 1959-03-31 00:00:00 0.000 2710.349 5.800 -0.505690 -1.090732 -2.123859
# 1959-06-30 00:00:00 2.340 2778.801 5.100 -0.940028 -2.204997 -1.195357
# 1959-09-30 00:00:00 2.740 2775.488 5.300 -0.636424 0.510898 1.105585
# 1959-12-31 00:00:00 None 2785.204 None NaN -0.203154 NaN
(4)註意,pivot其實只是一個快捷方式而己:用set_index創建層次化索引,再用unstack重塑。
unstacked=ldata.set_index([‘date‘,‘item‘]).unstack(‘item‘)
print unstacked[:7]
#輸出結果如下:
# value value2
# item infl realgdp unemp infl realgdp unemp
# date
# 1959-03-31 00:00:00 0.000 2710.349 5.800 -0.380805 -2.499867 -1.398593
# 1959-06-30 00:00:00 2.340 2778.801 5.100 -0.168914 0.435372 -1.454938
# 1959-09-30 00:00:00 2.740 2775.488 5.300 -0.297850 -1.693196 1.615807
# 1959-12-31 00:00:00 None 2785.204 None NaN 1.551105 NaN
import pandas as pd
import numpy as np
from pandas import Series,DataFrame
df = pd.DataFrame({‘foo‘: [‘one‘, ‘one‘, ‘one‘, ‘two‘, ‘two‘,
‘two‘],
‘bar‘: [‘A‘, ‘B‘, ‘C‘, ‘A‘, ‘B‘, ‘C‘],
‘baz‘: [1, 2, 3, 4, 5, 6],
‘zoo‘: [‘x‘, ‘y‘, ‘z‘, ‘q‘, ‘w‘, ‘t‘]})
print df
#輸出結果如下:
# bar baz foo zoo
# 0 A 1 one x
# 1 B 2 one y
# 2 C 3 one z
# 3 A 4 two q
# 4 B 5 two w
# 5 C 6 two t
print df.pivot(index=‘foo‘,columns=‘bar‘)[‘baz‘] #行索引foo,列bar,值baz
#輸出結果如下:
# bar A B C
# foo
# one 1 2 3
# two 4 5 6
print df.pivot(index=‘foo‘,columns=‘bar‘,values=‘baz‘) #與上面的一致
# print df.pivot(index=‘foo‘,columns=‘bar‘,values=[‘baz‘, ‘zoo‘])
#若是兩行的索引一樣的話會報錯,因為值就不知道對應哪個了
#如下例中bar中的兩個索一樣
df=pd.DataFrame({"foo":[‘one‘,‘one‘,‘two‘,‘two‘],
"bar":[‘A‘,‘A‘,‘B‘,‘C‘],
"baz":[1,2,3,4]})
print df
print df.pivot(index=‘foo‘,columns=‘bar‘,values=‘baz‘) #報錯,foo,bar為[one,A]不知道對應哪個值了,兩個一樣的索引
- 數據轉換:
前面講的都是數據重排,另一類重要操作則是過濾、清理以及其它的轉換工作。
(1)drop_duplicates:刪除重復數據
(2)map:函數或映射進行數據轉換(map,lambda),map用於修改對象的子集
(3)fillna: 用於填充缺失數據,看做值替換的一種特殊情況。或者用pandas的replace方法替換缺失值(與python的str.replace方法一樣)
(4)rename:復制DataFrame並對其行索引和列標簽進行修改。若要就地修改某個數據集,傳入inplace=True即可
(5)cut:將數據劃分階段(即元面)例不同的年齡階段,它返回的Categorical對象。而qcut是根據樣本分位數對數據進行劃分(可以等分)
(6)abs:過濾絕對值,np.abs(data)>3取絕對值>3的數。
(7)np.sign:過濾的區間為-1到1的數組,表示原始值的符號。
(8)take:選取子集,從DataFrame或Series中選取部分子集
(9)get_dummies:DataFrame的某一列中有多個不同的值,可將該列的值作為列名,其值全為1和0.例:第一行只有a的值,則a為1,其它為0
Series只有panda.str.get_dummies.
pandas數據大發888平臺出租規整化:清理、轉換、合並、重塑