--- tags: Python --- # Pandas [Pandas cheat sheet pandas功能簡介](https://github.com/pandas-dev/pandas/blob/master/doc/cheatsheet/Pandas_Cheat_Sheet.pdf) ### 建立資料表 ``` #建立空欄位 pd.DataFrame(columns=['col_name']) #透過dict&list建立 pd.DataFrame({'col1'=list1,'col2'=list2}) #透過concat串接一維ndaarray、list pd.concat([ndarray1,ndarray2],names=['col1','col2']) #透過二維list建立 pd.DataFrame(item for item in list) #透過array dictionary建立 pd.DataFrame([{'a':123,'b':456}]) ``` ### 讀取資料 ``` #讀取csv、txt(使用中文路徑需加 engine='python') df = pd.read_csv(path) #讀取excel方法一 df = pd.read_excel(path,sheet_name='sheet1', engine='openpyxl') #讀取excel方法二 xlsx = pd.ExcelFile('.xlsx') sheets = xlsx.sheet_names df = xlsx.parse(sheets[0]) #讀取網頁上的table(讀完會生成list型態) df = pd.read_html(url_path)[0] ``` ### 輸出資料 ``` # 尾端加上 index=0 去掉預設的擾人索引值 df.to_csv(path,index=0) writer = pd.ExcelFile('.xlsx') df.to_excel(writer,sheet_name='mySheet',index=0) writer.close() df.to_json(path,orient='record') ``` ### 基礎統計運算 ``` df.describe() #秀出統計資料 df.mean() #平均值 df.std() #標準差 df.skew() #偏態 df.kurtosis() #峰態 df.corr() #欄位相關系數矩陣 df.sum() #縱向加總 df.T.sum().T #橫向加總 df.col.value_counts() #欄位的資料類別統計 ``` ### 資料型態 ``` df.shape #dataframe維度 df.info() #dataframe資料型態列表 df.col.astype(str) #轉成字串 df.col.astype(int) #轉成整數 df.col.astype(float) #轉成浮點數 df.col.astype('datetime64[ns]') #轉成timpstamp物件 df.col.date.dt.day #從時間物件中取出日期 ``` ### 篩選 ``` #頭尾篩選 df.head(10) df.tail(10) #取出特定欄位並轉成pandas series物件 df.col #懶得打中括號和引號的時候 df['col'] #如果欄位是中文字或是尷尬的英文字就得用這個 #行列篩選 df.loc[:,['col1','col2']] #依欄位名稱 df.iloc[:,[1,3,5]] #依欄位序號 df.ix[[1,3,5],['col1','col2']] #混搭兩者(deprecated) df[row][col] #不套函式 #轉成ndarray df.values #二維陣列 df.col.values #一維陣列 #轉成list df.tolist() #二維列表 df.col.tolist() #一維列表 #條件篩選(傳入True和False的ndarray) df[df.col.isin(ndarray)] #是否包含陣列內的物件 df[df.col.isnull()] df[df.col.notnull()] df[df.col.str.contains(string)] #欄位的文字是否有特定的字串 df[df.col.duplicated()] #抓出重複的值 #多重條件篩選 constraint_1 = df.col.notnull() constraint_2 = df.col.str.contains('abc') df[constraint_1 & constraint_2] ``` ### 新增刪除更改欄位 ``` df['col'] = np.nan #新增空欄位 df.drop(columns=['col']) #刪除欄位 df.rename(columns={'old_col':'new_col'}) #更改欄位名稱 df.columns = ['col1','col2'] #換上一整組新的欄位名稱 ``` ### 索引 ``` df.index df.reset_index(drop=True) #重設索引並且把原本的索引刪除 ``` ### 排序 ``` #依索引排序(ascending=False 從大到小) df.sort_index(ascending=False) #依欄位值排序 df.sort_values(by='col', ascending=False) #依據單一欄位 df.sort_values(by=['year','month','day']) #依據多欄位、順序 ``` ### 空值處理 ``` #空值、非空值分布狀況 df.isnull().any() df.col.isnull().sum() df.col.notnull().sum() #篩選有空值、非空值的row df[df.col.isnull()] df[df.col.notnull()] #去除、填上空值 df.dropna(how='any') #去除其一欄位為空者 df.dropna(how='all') #去除整行欄位為空者 df.dropna(thresh = 3) #至少有三欄不為空 df.fillna(0) #以0替代空值 df.fillna(method='ffill') #以不為空值的前者補上 df.fillna(method='bfill') #以不為空值的後者補上 #空值插補(沒有所謂最好的) df.col.interpolate(method='linear') #其他方法 linear, nearest, zero, slinear, quadratic, cubic, barycentric ``` ![](https://i.imgur.com/4iRXGCJ.png) ### 重複值處理 ``` #取得非重複值 df.col.unique() #欄位內所有種類 #去除重複值 df.drop_duplicates() #去除整行欄位重複者 df.drop_duplicates('col',keep='first') #遇到重複值只保留第一個 df.drop_duplicates('col',keep='last') #遇到重複值只保留最後一個 #篩選重複值 df.col.duplicated() ``` ### 時間序列 [想要深造時間序列模型請點我](https://www.kaggle.com/thebrownviking20/everything-you-can-do-with-a-time-series) ``` #轉成時戳物件 pd.to_datetime('2017-11-11 09:08:07') pd.to_datetime('col',format='%Y-%m-%d %H:%M:%S') #時戳物件TimeStamp()常用函數 .date、.time .year、.month、.day #日期 .hour、.minute、.second #時間 .daysinmonth #一個月有幾天 .weekday #星期幾(0~6)(一~日) #轉成時差物件(兩個時戳物件互相加減變換轉換成時差物件) pd.timedelta('00:30:00') .total_seconds() #常用函數->總秒數 #產生時間範圍 pd.date_range(start='1/1/2018', periods=5, freq='M') #產生五個時間點、以月分作為間隔 #時序取樣 df.resample(on='datetime',freq='30min').mean() df.col.asfreq('30min') df.col.rolling('7D').mean() #7天的移動平均(往前取樣,因此取樣的最後一天才有值) df.col.expanding('7D').mean() #7天平均(往後取樣,因此前6天值不為空值) ``` ### 字串處理 ``` df.col.str.contains(str1|str2) #抓出涵蓋字串1和2的文字 df.col.str[1:-1] #將字串頭尾去掉 df.col.str.extract(r'') #使用正規表達式抽出字串 df.col.str.replace('不要的字串','') #去除掉不要的字串 df.col.astype('category').cat.codes #轉成category物件並重新編號 df.col.map({0:''winner',1:'chicken',2:'dinner'}) #使用字典替代特定資料 ### 判斷是否含有中文字 def is_chinese(uchar): return True if u'\u4e00'<=uchar<=u'\u9fff' else False ``` ### 更改欄位資料 ``` #套用預設函數 df.col.map(np.sqrt) #使用lambda進行三元運算 df.col.map(lambda x:x**2 if x>0 else x) #自訂函數 def my_function(x): return x**2 df.col.map(my_function) ``` ### 資料表串接 ``` #橫向串接(指定串接欄位與串接方式) pd.merge(df1,df2,on=['col_1','col_2'], how='left', suffix=['_x','_y']) #how種類 left, right, inner, outer #suffix用於兩個表中欄位名稱一樣但沒有加入on裡面,因此加入詞綴來重新命名 #上下縱向串接(欄位名稱需一致) df1.append(df2) ``` ### 資料表展開、溶解 ``` #展開(將三個欄位展開,各別給上新索引、欄位、值) df.pivot(index='col1',columns='col2',values='col3') df.groupby('col').sum().unstack() #溶解(反展開,將整張表轉換成三個欄位) pd.melt(df,id_vars='唯一值類別的欄位') ``` ### 群組分析 ``` df.groupby(['col1','col2'])['col3'].mean() df.groupby(['col1','col2'])['col3'].median() df.groupby(['col1','col2'])['col3'].quantile(0.5) df.groupby(['col1','col2'])['col3'].count() df.groupby(['col1','col2'])['col3'].size() df.groupby(['col1','col2'])['col3'].sum() df.groupby(['col1','col2'])['col3'].describe() df.groupby(['col1','col2'])['col3'].count().unstack()#群組統計並且pivot #grouby之後索引會變成 multi index,再加上.reset_index()可以回復原本單索引的DataFrame df.groupby(['col1']).apply(lambda dataframe: ...) for index, dataframe in df.groupby(['col1']): pass ``` ### 隱藏警告 ``` # 常常在做資料處理的時候會顯示出超長的warining,這裡有個方法可以隱藏 import warnings warnings.filterwarnings('ignore') ``` ### 讀取政府的開放資料(ods, pdf) > [open document](https://github.com/T0ha/ezodf) ``` import ezodf def read_ods(filename, sheet_no=0, header=0): tab = ezodf.opendoc(filename=filename).sheets[sheet_no] return pd.DataFrame({col[header].value:[x.value for x in col[header+1:]] for col in tab.columns()}) df = read_ods(path, header=1) header代表前面要先空個幾行再進行讀取 ``` > [pdf](https://github.com/chezou/tabula-py) ``` from tabula import read_pdf df = read_pdf(PDF網址,encoding = 'big5', spreadsheet = True, pages = '1-10') encoding 大多數的中文字編碼為big5 spreadsheet 是否為表單格式 pages 要抓取的頁數 ``` ### numpy pandas是基於numpy的高階程式庫,了解numpy本身怎麼寫也是蠻重要的 ```python import numpy as np ### 資料格式 np.array(list) #從list轉為np陣列(ndarray) ndarray.shape #各個維度的大小 ndarray.dtype #資料型態 ndarray.ndim #資料維度 ndarray.size #資料尺寸 ndarray.itemsize #資料格式記憶體大小 ### 陣列處理 ndarray.flat #攤開變成一維 ndarray.resize((x,y)) ndarray.T ndarray.reshape(x,-1) #-1代表自動計算 np.squeeze(ndarray) #將陣列壓成一維 ### 陣列篩選 ndarray[1:-1] #第二個到倒數第二 ndarray[::2] #每隔兩行篩選出來 ### 陣列簡單運算 ndarray + ndarray_row #列相加 ndarray + ndarray[:,np.newaxis] #行相加 ### 線性代數 Linear Algebra np.eye(3) #eye代表線性代數中的I np.identity(3) #同於np.eye() np.diag(ndarray) #取出陣列對角線的值 ndarray.transpose() #轉置矩陣,同於ndarray.T np.dot(np.sin(), np.cos()) #內積 dot product np.outer(np.sin(), np.cos()) #外積 cross product np.linalg.inv(ndarray) #反轉矩陣 np.linalg.solve(x,y) #矩陣相乘 #產生一維陣列 np.arange(0,15,1) #最後一個值代表數值間隔 np.linspace(0,15,5) #最後一個值代表產生的數量 np.r_[1:4,0,4] #橫向產生[1,2,3,4,0,4] np.c_[1:4,0,4] #縱向產生 #產生高維陣列 np.zeros((x,y,z)) np.ones((x,y,z)) np.empty((x,y,z)) def func(x,y): return 10*x+y np.fromfunction(func,(x,y),dtype=int) #隨機產生 np.random.randint(50,size=20) np.random.random((x,y,z)) np.random.normal(平均值,sigma,數量) np.histogram(ndarray,bins=50,norm=True) ### 陣列串接 np.concatenate([list1,list2]) #一維合併 np.vstack((n1,n2)) #垂直合併 np.hstack((n1,n2)) #水平合併 np.columns_stack((n1,n2)) #橫向合併 ### 陣列分割 np.hsplit(ndarray,3) 水平切成3個ndarray np.vplit(ndarray,3) 垂直切成3個ndarray ### 儲存、載入 np.save('filename.npy',ndarray) ndarray = np.load('filename.npy') ``` ## 用R語言做報告 > 如果課堂作業必須用R語言的話... RMD輸出PDF的方法(擺脫office word的束縛): 安裝[VSCODE萬用程式碼編輯器](https://code.visualstudio.com/) 安裝[R語言](https://cran.r-project.org/bin/windows/base/) 安裝[Pandoc](https://pandoc.org/installing.html) 在VScode的Extensions(ctrl+shift+x開啟),搜尋R並安裝擴充套件 創建一個`.rmd`檔,填入安裝rmarkdown與knitr的指令: ```r install.packages("rmarkdown") install.packages("knitr") ``` 將程式碼片段框起來,使用快捷鍵`ctrl+enter`執行 RMD基本語法: * 控制輸出圖案的大小 `{r,fig.width=3,fig.height=3}` * 以latex語法輸入數學式 `{=latex}` 打完Markdown語法後,按下右上的`Knit RMD`(ctrl+shift+k)輸出HTML, 用瀏覽器開啟HTML,滑鼠右鍵>列印>另存成PDF