---
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
```

### 重複值處理
```
#取得非重複值
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