Pandas基礎篇 Pandas基於Numpy開發,提供了很多高級的數據處理功能。 1、Pandas中的數據對象 Series和DataFrame是Pandas中最常用的兩個對象。 1.1 Series對象 是Pandas中最基本的對象,可用Numpy的數組處理函數直接對Series對象進行處理。支 ...
Pandas基礎篇
Pandas基於Numpy開發,提供了很多高級的數據處理功能。
1、Pandas中的數據對象
Series和DataFrame是Pandas中最常用的兩個對象。
1.1 Series對象
是Pandas中最基本的對象,可用Numpy的數組處理函數直接對Series對象進行處理。支持使用位置、索引標簽作為下標存取元素,與字典類似;每一個Series對象實際上由兩個數組組成。
print(pd.__version__)
s=pd.Series([1,3,2,4,5],index=['b','a','c','d','e'])#若index不指定,將自動創建位置下標的索引
print('索引:',s.index)
print('數組值:',s.values)
print('位置下標:',s[2])
print('標簽下標:',s['a'])
print('位置切片:',s[1:3])
print('標簽切片:',s['a':'c'])
print('位置列表存取元素:',s[[1,2,3]])#按照標簽的位置
print('標簽數組存取元素:',s[['b','c','d']])
print('字典功能:',list(s.iteritems()))
s2=pd.Series([20,30,40,50,60],index=['b','c','d','e','f'])
print(s+s2)#兩邊index都有則相加即可,若有一方沒有,則用NaN填充
print(s.value_counts())#元素中每個值得個數
str=pd.Series(['A','b','C','是','Baca',np.nan,'VASD','dafd'])
print(str.str.lower())# 對英文字母小寫
1.2 DataFrame 對象
DataFrame對象(數據表)是Pandas中最常用的數據對象。Pandas提供了很多數據結構轉換成DataFrame對象的方法,還提供很多輸入輸出函數來將各種文件格式轉換成DataFrame對象。
dates = pd.date_range('20130101', periods=6)#periods為個數
調用read_csv讀取數據,通過index_col指定第0,1列為索引,用parse_dates參數指定進行日期轉換列.在指定列時可以使用列的序號或列明。
df_soil=pd.read_csv('Soils-simple.csv',index_col=[0,1],parse_dates=['Date'])
df_soil=pd.read_csv('Soils-simple.csv',index_col=[0,1],parse_dates=['Date'])
df_soil.columns.name='Measures'
DataFrame對象是一個二維表格,其中每列中的元素必須一致,而不同列則可不同。object可保存任何python對象
print(df_soil.dtypes)#dtypes屬性獲得表示各個列類型的Series對象。
print(df_soil.shape)#行數和列數
print(df_soil)
print(df_soil.head(1))#查看頂部幾條數據
print(df_soil.tail(1))#查看底部幾條數據
print(df_soil.index)#查看行索引
print(df_soil.columns)#查看列索引
print(df_soil.values)#查看底層numpy的數據
print(df_soil.describe())#快速統計數據
print(df_soil.T)#行列互換
print(df_soil.sort_index(axis=0,ascending=False))#根據軸排序,axis為1表橫軸,反之縱軸,ascending為True表正序,反之 反序
print(df_soil.sort_values(by='pH'))#按照值排序,指定某縱軸對應的值,列排序
#DataFrame對象用油行索引和列索引,並可通過索引標簽對數據進行存取。
print('columns:',df_soil.columns)# 列索引
print('index:',df_soil.index)# 行索引
print('columnsname:',df_soil.columns.name)
print('indexname:',df_soil.index.name)
#運算符可通過列索引標簽獲取指定列,當下標是單個便簽時,所得到的是Series對象,當下標是列表時,則是新的DataFrame對象。
print('pH:',df_soil['pH'])
print('Dens,Ca:',df_soil[['Dens','Ca']])
#通過行索引獲取指定的行
print('df.loc:',df_soil.loc['0-10','Top'])
print('df.loc:',df_soil.loc[['10-30']])
print(df_soil.values.dtype)
print('===============將記憶體中的數據轉換成DataFrame對象===================')
import numpy as np
# 將形狀為4,2的二維數組轉換成DataFrame對象,通過index和columns參數指定行和列的索引
df1 = pd.DataFrame(np.random.randint(0, 10, (4, 2)), index=['A', 'B', 'C', 'D'], columns=['a', 'b'])
# 將字典轉換成DataFrame,列索引有字典的鍵決定,行索引有index參數指定
df2 = pd.DataFrame({'a': [1, 2, 3, 4], 'b': [5, 6, 7, 8]}, index=['A', 'B', 'C', 'D'])
# 將結構數組轉行成DataFrame對象,列索引由結構數組的欄位名決定,行索引預設從0開始的整數序列。
df3 = pd.DataFrame(
np.array([('item1', 1), ('item2', 2), ('item3', 3), ('item4', 4)], dtype=[('name', '10S'), ('count', 'int')]))
print(df1)
print(df2)
print(df3)
dict1 = {'a': [1, 2, 3], 'b': [4, 5, 6]}
dict2 = {'a': {'A': 1, 'B': 2}, 'b': {'A': 3, 'C': 4}}
# orient參數指定字典鍵對應的方向,預設columns,表示把字典的鍵轉換成為列索引
df1 = pd.DataFrame.from_dict(dict1, orient='index')
df2 = pd.DataFrame.from_dict(dict1, orient='columns')
df3 = pd.DataFrame.from_dict(dict2, orient='index')
df4 = pd.DataFrame.from_dict(dict2, orient='columns')
print(df1)
print(df2)
print(df3)
print(df4)
df1 = pd.DataFrame.from_items(dict1.items(), orient='index', columns=['A', 'B', 'C'])
df2 = pd.DataFrame.from_items(dict1.items(), orient='columns')
print(df1)
print(df2)
print("======將DataFrame對象轉換成其他格式的數據======")
print(df2.to_dict(orient='records'))#字典列表
print(df2.to_dict(orient='list'))#列表列表
print(df2.to_dict(orient='dict'))#嵌套字典
print(df2.to_records(index=False).dtype)#轉換成結構數組,index表示返回是否行索引數據
print(df2.to_records(index=True).dtype)#轉換成結構數組,index表示返回是否行索引數據
np.random.seed(42)
dates =pd.Index(['r1','r2','r3','r4','r5'],name='level')
df=pd.DataFrame(np.random.randint(0,10,(5,3)),index=dates,columns=['c1','c2','c3'])
print(df)
pieces=[df[:2],df[2:4],df[4:]]
print(pd.concat(pieces))#連接
left=pd.DataFrame({'key':['foo','foo'],'lval':[1,2]})
right=pd.DataFrame({'key':['foo','foo'],'rval':[4,5]})
print(pd.merge(left,right,on='key'))# 將一樣key的值對應鏈接
left=pd.DataFrame({'key':['foo','bar'],'lval':[1,2]})
right=pd.DataFrame({'key':['foo','bar1'],'rval':[4,5]})
print(pd.merge(left,right,on='key'))# 將一樣key的值對應鏈接
print(df.append(df.iloc[3],ignore_index=False))# 添加第4行,ignore_index表示忽略給的行號 自動標從0開始。
print(df[['c1']])
print(df[['c1','c2']])
print(df[2:4])#表示第2行到第4-1行
print(df['r2':'r4'])#表示第2行到第4-1行
print(df[df.c1>4])#c1列大於4的行
print(df[df>2])#對象中大於2的顯示,否則用NaN填充
df2=df.copy()
df2['c4']=[1,2,3,4,5]
print(df2)
print(df2['c4'].isin([1,2,3]))#篩選c4列中值為1,2,3的為True
df = pd.DataFrame(np.random.randn(6,4), index=dates, columns=list('ABCD'))
df1 = df.reindex(index=dates[0:4], columns=list(df.columns) + ['E'])#放大或縮小原df
# df1.loc[dates[0]:dates[1],'E'] = 1
print(df1)
print(df1.dropna(how='any'))#刪除所有有NaN的行
print(df1.fillna(value=5))#將所有NaN的值轉換成5
print(df1.isnull())#將每個位置的值判斷是否nan
print(df)
print(df.mean())#每列的平均值
print(df.mean(1))#每行的平均值
s=pd.Series([1,3,5,np.nan,6],index=dates)
print(s)
print(s.shift(1))#在最前面放1個nan,然後再加入s,長度為原來的長度
print(df.sub(s,axis='index'))#對應s的行減去s的位置的值。減nan,則成nan
print(df.apply(np.cumsum))#累積求和,從列的上到下
print(df.apply(lambda x:x.max()-x.min()))#一列中的最大減去最小
dfgroup = pd.DataFrame({'A' : ['foo', 'bar', 'foo', 'bar','foo', 'bar', 'foo', 'foo'],
'B' : ['one', 'one', 'two', 'three','two', 'two', 'one', 'three'],
'C' : np.random.randn(8),'D' : np.random.randn(8)})
print(dfgroup.groupby('A').sum())# 通過A列中的值,求出同樣值的和
print(dfgroup.groupby('A').size())# 通過A列中的值,求出同樣值的個數
print(dfgroup.groupby(['A','B']).sum())# 通過A、B列中的值,求出同樣值的和
tuples = list(zip(*[['bar', 'bar', 'baz', 'baz',
'foo', 'foo', 'qux', 'qux'],
['one', 'two', 'one', 'two',
'one', 'two', 'one', 'two']]))
index = pd.MultiIndex.from_tuples(tuples, names=['first', 'second'])
df = pd.DataFrame(np.random.randn(8, 2), index=index, columns=['A', 'B'])
print(df[:4])
df2 = df[:4]
print(df2.stack())#將列對應加入行,變成原行*列的行數
print(df2.stack().unstack())#變回來
print(df2.stack().unstack(1))# 將多級索引中第2個變為列
print(df2.stack().unstack(0))# 將多級索引中第1個變為列
df = pd.DataFrame({'A' : ['one', 'one', 'two', 'three'] * 3,
'B' : ['A', 'B', 'C'] * 4,
'C' : ['foo', 'foo', 'foo', 'bar', 'bar', 'bar'] * 2,
'D' : np.random.randn(12),
'E' : np.random.randn(12)})
print(pd.pivot_table(df, values='D', index=['A', 'B'], columns=['C']))# 將D列數據拿出來,行為A、B排列組合,列為C中的值
rng = pd.date_range('1/1/2012', periods=100, freq='S')# 時間排100s freq表示單位
# print(rng)
ts = pd.Series(np.random.randint(0, 500, len(rng)), index=rng)
print(ts.resample('5Min').sum())#列印5分鐘內的總數
1.3 Index對象
Index對象保存索引標簽數據,它可快速找到標簽對應的整數下標
index=df_soil.columns
print(index)
print(index.values)
# Index對象可當做一維數組,可通過NumPy數組相同的下標操作獲取新的Index對象,但是只可讀,不可改。
print(index[[1,3]])
print(index>'c')
print(index[index>'c'])
print(index[1::2])
# 獲取映射值
print(index.get_loc('Ca'))#獲取位置
print(index.get_indexer(['Dens','Conduc']))#以數組排序,若不存在 返回-1
# 可直接調用Index()創建Index對象,再傳遞給DataFrame的index或columns,又由於Index不可變,則多個數據可共用一個Index對象
index=pd.Index(['A','B','C'],name='level')
s1=pd.Series([1,2,3],index=index)
df1=pd.DataFrame({'a':[1,2,3],'b':[4,5,6]},index=index)
print(s1.index,df1.index)
1.4 MultiIndex對象
MultiIndex對象表示多級索引,繼承Index,其中的多級標簽採用元組對象表示
mindex=df_soil.index
print(mindex[1])
print(mindex.get_loc(('0-10','Slope')))
print(mindex.get_indexer([('10-30','Top')]))
# 內部並不直接保存元組對象,而是使用多個Index對象保存索引中每級的標簽
print(mindex.levels[0])
print(mindex.levels[1])
#使用多個整數數組保存標簽下標
print(mindex.labels[0])
print(mindex.labels[1])
# 獲得所有元組列表
level0,level1=mindex.levels
label0,label1=mindex.labels
print(list(zip(level0[label0],level1[label1])))
# 將一個元組列表傳遞給Index()時,將自動創建MultiIndex對象
print(pd.Index([('A','x'),('A','y'),('B','x'),('B','y')],name=['class1','class2'],tupleize_cols=True))#tupleize_cols參數表示是否為MultiIndex對象
print(pd.MultiIndex.from_arrays([['A','A','B','B'],['x','y','x','y']],names=['class1','class2']))#多個數組創建MultiIndex對象
midx=pd.MultiIndex.from_product([['A','B','C'],['X','Y']],names=['class1','class2'])#使用笛卡爾積創建MultiIndex對象
print(midx)
print(pd.DataFrame(np.random.randint(0,10,(6,6)),columns=midx,index=midx))
1.5 常用的函數參數
參數 | 常用值 | 說明 |
axis | 0、1 | 運算對應的軸 |
level | 整數或索引的級別名 | 指定運算對應的級別 |
fill_value | 數值 | 指定運算中出現的NaN的代替填充值 |
skipna | 布爾值 | 運算是否跳過NaN |
index | 序列 | 指定行索引 |
columns | 序列 | 指定列索引 |
numeric_only | 布爾值 | 是否只針對數值進行運算 |
func | 可調用函數 | 指定回調函數 |
inplace | 布爾值 | 是否原地更新,若為否,則返回新對象 |
encoding | utf8 | 指定文本編碼 |
dropna | 布爾值 | 是否刪除包好NaN的行 |
2、下標存取
2.1 []操作符
通過[]操作符對DataFrame對象進行存取時,支持以下5中下標對象:
import numpy as np
np.random.seed(42)
df=pd.DataFrame(np.random.randint(0,10,(5,3)),index=['r1','r2','r3','r4','r5'],columns=['c1','c2','c3'])
print(df)
單個索引標簽:獲取標簽對應的列,返回一個Series對象。
print(df[['c1']])
多個索引標簽:獲取以列表、數組(註意不能是元組)表示多個標簽對應的列,返回一個DataFrame對象
print(df[['c1','c2']])
整數切片:以整數下標獲取切片對應的行。
print(df[2:4])#表示第2行到第4-1行
標簽切片:當使用標簽作為切片時包含終值。
print(df['r2':'r4'])#表示第2行到第4-1行
布爾數組:獲取數組中True對應的行。
print(df[df.c1>4])#c1列大於4的行
布爾DataFrame:將DataFrame對象中False對應的元素設置為NaN。
print(df[df>2])#對象中大於2的顯示,否則用NaN填充
2.2 .loc[]和.iloc[]存取器
print(df.loc['r2'])#r2行
print(df.loc['r2','c2'])#第r2行的第c2列
print(df.loc[['r2','r3']])#r2,與r3行
print(df.loc[['r2','r3'],['c2','c3']])#r2和r3所對應的c2於c3列
print(df.loc['r2':'r4',['c2','c3']])#r2到r4所對應的c2,c3列
print(df.loc[df.c1>2,['c1','c2']])#c1列大於2的c1與c2列
.iloc與.ioc類似,不過它是使用整數下標。
print(df.iloc[1])#r2行
print(df.iloc[[1,2]])#r2,與r3行
print(df.iloc[[1,2],[1,2]])#r2和r3所對應的c2於c3列
print(df.iloc[1:3,[1,2]])#r2到r4所對應的c2,c3列
print(df.iloc[df.c1.values>2,[0,1]])#c1列大於2的c1與c2列
.ix[]存取器,混用標簽和位置下標。
print(df.ix[2:4,['c1','c2']])
print(df.ix['r1':'r3',[0,1]])
獲取單個值
print(df.at['r2','c2'])
print(df.iat[1,1])
print(df.get_value('r2','c2'))#比.at速度要快
print(df.lookup(['r2','r4','r3'],['c1','c2','c1']))#獲取指定元素數組
多級標簽的存取
print(df_soil.loc[np.s_[:'Top'],['pH','Ca']])#np.s_對象創建第0軸對應的下標。
query()方法
print(df.query('c1>3 and c2<4'))#條件查詢 可使用no、and、or等關鍵字,可使用全局變數
low=3
hi=4
print(df.query('c1>@low and c2<@hi'))
3、文件的輸入輸出
輸入輸出函數
函數名 | 說明 |
read_csv() | 從CSV格式的文本文件讀取數據 |
read_excel() | 從Excel文件讀入數據 |
HDFStore() | 使用HDF5文件讀寫數據 |
read_sql() | 從SQL資料庫的查詢結果載入數據 |
read_pickle() | 讀入Pickle序列化之後的數據 |
3.1 CSV格式
df_list=[]
for df in pd.read_csv(
'201406.csv',
encoding='utf-8',#編碼
chunksize=100,#一次讀入的行數
usecols=['時間','監測點','AQI','PM2.5','PM10'],#只讀入這些列
na_values=['-',''],#這些字元串表示缺失數據
parse_dates=[0]#第一列為時間列
):
df_list.append(df)
print(df_list[0].count())
print(df_list[0].dtypes)
df.to_csv('foo.csv')#寫入數據
df.to_excel('foo.xlsx', sheet_name='Sheet1')#寫入數據
pd.read_excel('foo.xlsx', 'Sheet1', index_col=None, na_values=['NA'])#讀取數據
3.2 HDF5文件
HDF5用於存儲科學計算數據,支持大於2G的文件。採用二進位格式保存數據,可以對數據進行壓縮存儲,比文本文件更節省空間,存取也更迅速。
df.to_hdf('foo.h5','df')#寫入數據
pd.read_hdf('foo.h5','df')#讀取數據
store=pd.HDFStore('a.hdf5',complib='blosc',complevel=9)#complib指定使用blosc壓縮數據,通過complevel指定壓縮級別
df1=pd.DataFrame(np.random.rand(100000,4),columns=list('ABCD'))
df2=pd.DataFrame(np.random.randint(0,1000,(10000,3)),columns=['one','two','three'])
s1=pd.Series(np.random.rand(1000))
store['dataframes/df1']=df1
store['dataframes/df2']=df2
store['dataframes/s1']=s1
print(store.keys())
print(df1.equals(store['dataframes/df1']))
root=store.get_node("//")#獲取根節點,
for node in root._f_walknodes():#調用_f_walknodes()遍歷其包含的所有節點。
print(node)
#往已保存進HDFStore的DataFrame追加數據
store.append('dataframe/df_dynamic1',df1,append=False)#append為False表示是否覆蓋已存在的數據
df3=pd.DataFrame(np.random.rand(100,4),columns=list('ABCD'))
store.append('dataframe/df_dynamic1',df3)
print(store['dataframes/df_dynamic1'].shape)
#使用append()創建pytables中支持索引的表格(Table)節點,預設使用DataFrame的index作為索引。通過select可對其進行查詢 index表DataFrame的標簽數據
print(store.select('dataframe/df_dynamic1',where='index>97 & index<102'))#表示行在97-102所有的行,該方法減少記憶體使用量和磁碟讀取速度以及數據的訪問速度,在添加df3時是添加不是覆蓋,所以有兩個98,99
#若希望對DataFrame的指定列進行索引,可以在用append創建新的表格時,通過data_columns指定索引列
store.append('dataframes/df_dynamic1', df1, append=False, data_columns=['A', 'B'])
print(store.select('dataframes/df_dynamic1' , where='A > 0.99 & B <0.01'))
在將對個文本文件的數據逐次寫入HDF5文件時,需要註意以下幾點:
1.HDF5文件不支持Unicode字元串,因此需要對Unicode字元串進行編碼,轉換為位元組字元串。由於文件可能包含UTF-8的BOM,因此在讀取文件的頭三個位元組並與BOM比較。
2.需要使用dtype參數指定這些數值列的類型為浮點數。
3.需要為HDF5文件中的字元串列指定最大長度,否則該最大長度將由第一個被添加進HDF5文件的數據對象決定。
註意:由於所有從CSV文件讀入DataFrame對象的行索引都為預設值,因此HDF5文件中的數據的行索引並不是唯一的。
3.3 Pickle序列化
df = pd.DataFrame(np.random.randint(0, 10, (4, 2)), index=['A', 'B', 'C', 'D'], columns=['a', 'b'])
df.to_pickle('df.pickle')
df_aqi2=pd.read_pickle('df.pickle')
print(df.equals(df_aqi2))