Photo by Michael Payne on Unsplash

使用 Pandas DataFrame 常用的 27 個基本技巧

Eric Tsai
11 min readMar 28, 2021

本篇文章主要分四個部分,第一個部分是 dataframe 的基本操作,第二是過濾資料或找特定資料的方法,第三是 dataframe 資料分組的操作,最後一個部分則是我個人常用到的資料處理技巧

Dataframe 的基本操作

  1. 在本地主機載入和儲存 dataframe
import pandas# csv
df = pd.read_csv('./file_name.csv')
# json
df = pd.read_json ('./file_name.json')
# pikle
df = pd.read_pickle('./file_name.pkl')
# excel
df = pd.read_excel('./file_name.xlsx', sheet_name='sheet_name_1')

2. 從SQL Server 載入 dataframe

import pyodbccnxn = pyodbc.connect('Trusted_Connection=yes', driver='{SQL Server}', server='tcp:myserver')
cursor = cnxn.cursor()
sql = f'''
sql code here
'''
df = pd.read_sql(sql, cnxn)
cursor.close()
cnxn.close()

3. 將 data frame 輸出到本地主機

# csv
df.to_csv('./file_name.csv')
# json
df.to_json('./file_name.json')
# pikle
df.to_pickle('./file_name.pkl')
# excel
df.to_excel("file_name.xlsx", sheet_name='Sheet_name_1')

4. 手動建立 data frame

分別有兩種方法,一種是用矩陣表達資料樣式,另一種是用字典方式將資料轉換成 data frame

# create dataframe by matrix
data = [[1,2,3],
[4,5,6],
[7,8,9]]
pd.DataFrame(data, columns=['A','b','c'])
# create dataframe by dictionary
dic = {'A':[1,4,7],
'b':[2,5,8],
'c':[3,6,9]}
pd.DataFrame(dic)

5. 檢查 data frame 的資料

通常都是檢查前五列或後五列,展示的列數可以在括號內做調整

df.head()
df.tail()

6. data frame 重新命名

df.columns = ['name1', 'name2', 'name3']

7. 將特定欄位作為 data frame 的 index

df.set_index('A',inplace=True)

8. 透過特定欄位來合併兩個 data frame

df1 和 df2 都為 dataframe,how 為 data frame 合併的方式,比較常用的參數有 'inner' 、' left' 和 'right',如果熟悉 SQL 的人,這些合併方法應該不陌生,至於 left_on 和 right_on 則是合併兩個 data frame 所需要的 key 值

df1.merge(df2, how, left_on, right_on)

9. 串聯兩個 data frame

df3 = pd.concat([df1,df2], axis=1)

10. 重置 data frame 的 index,

data frame 的資料經過篩選後,index 會有跳號的情形,通常我們會透過下面的方法,重置 index

new_df = df.reset_index(drop=True,inplace=False)

11. 新增欄位到 data frame

# 我習慣的做法(會新增欄位到最後一欄)
df['new_col_name'] = data
# 但有時候你希望新增的欄位在指定的順序位置(ex.新增到第一欄)
df.insert(loc=0, column=’new_col_name’, value=1)

過濾資料和找特定資料的方法

12. 過濾 data frame 的資料

# 你想要A欄位大於10的資料,寫法如下
df.query("A>10")
# 你想要A欄位大於10,且B欄位小於12的資料,寫法如下
df.query("A>10 & B<12")

13. 透過 boolean(布林) 值,作為篩選指標

# 只回傳 column_name 等於 1 的資料列
df[df['column_name']==1]
# 只回傳 column_name1 和 column_name2 不是空值的資料列
df[df['column_name1'].notnull() & df['column_name2'].notnull()]
# 只回傳 column_name 有在出現在列表中的資料列
value_list = [1,3,5,7,9]
mask = df['column_name'].isin(value_list)
df[mask]

14. 透過 index 或欄位名稱找到 data frame 中的資料

Table1
df.iat[1,2]
out: 20
df.at[3,'A']
out: 2
df.loc[[1,3],['B','C']]
df.iloc[[1,3],[1,2]]
out:
B C
---------
1 0 20
3 0 0

Data Frame 資料分組的操作

15. data frame 資料分組

Data Frame 可以透過一個或多個欄位中的值進行分組,以上面 Table1的資料為例,如果透過A欄位進行分組,而A欄位只有 0, 1, 2 三種值的話,透過 groupby 可以將 data frame 分成相應的三組資料

df_groupby_A = df.groupby('A')
df_groupby_AB = df.groupby(['A' ,'B'])
# 我個人很常會用到 groupby 加 size 回傳 groupby 後欄位中各個數值的資料數量
df.groupby('A').size()

16. 取得分組資料

# 取得 A 欄數值是1的資料(列)
df_group_A.get_group(1)

17. 透過特定欄位來聚合其他欄位的資料

無論是分組進行統計相關計算(平均數、標準差等)或將其他欄位的資料透過列表儲存在 cell 當中,都是非常實用的技巧

test_group = df.groupby('A').agg({'A':sum, 'B': list})
test_group.reset_index(drop=True)
Table2

18. 轉置 data frame

df.T
Table1
Table3

資料處理技巧

19. apply

透過 apply 可以利用 function 一列一列的進行資料處理。另外有一個叫 swifter 的套件可以在 apply 的基礎上直接使用。

df['column_name1'].apply(function, axis=0)
df[['column_name1', 'column_name2']].apply(function, axis=1)
# use swifter
df['column_name'].swifter.progress_bar(False).apply(function)

20. np.vectorize

用法上幾乎跟 apply 一樣,主要差別在於 np.vectorize 有透過 numpy 套件在運算效能上進行優化,所以如果你撰寫的 function 裡面有越多東西可以轉移到 numpy,你運算的速度就會越快,但如果沒有,直接用 apply 會是更好的方法,有興趣可以參考這裡

np.vectorize(function)(df['column_name1'])

21. 依序疊代 data frame 的 row

請注意: 這不是一個好的資料處理方法,特別是資料龐大的時候,如果你確定要這麼做,請先確保其它更快的解決方案你都嘗試過了

# 透過 enumerate 可以依序回傳疊代的index(疊代到第幾次)和資料列
for index, row in enumerate(df['A']):
print(f'index: {index}, row: {row}')
# 透過 iterrows 和 itertuples 依序還傳資料列
for index, row in df.iterrows():
print(row['A'], row['B'])
for row in df.itertuples(index=True, name='Pandas'):
print(row.A, row.B)

22. 將有NA 值的列或欄丟棄

# axis=0 丟棄列,axis=1 丟棄欄
df.dropna(axis=0,inplace=True)
# 丟棄特定欄位
df.dropna(subset=['column_name'])

23. 重塑 data frame

將資料重塑成兩欄

pd.DataFrame(df.values.reshape(-1,2), columns=['A','B'])
Original Table
Reshape Table

24. 資料排序

df.sort_values(by='A', ascending = False)

資料處理技巧-進階

25. 丟棄滿足欄位名稱特定條件的欄位

假設今天有一個 data frame,欄位名稱分別為A_TW、B、C,但我們不想要結尾有 TW 的欄位,我們可以透過建構一個丟棄列表(其中包含所有結尾為TW 的欄位名稱)

droplist = [i for i in df.columns if i.endswith('TW')]
df.drop(droplist, axis=1, inplace=True)

26. 如果你有讀取 excel(xlsx file) 的經驗,有時候會出現以下狀況,這時你可以透過filter,過濾掉你不需要的欄位,跟上一個技巧有異曲同工之妙

df.drop(df.filter(regex="Unname"),axis=1, inplace=True)

27. 如果您習慣用 daat frame 整理資料的話,有時候你會遇到一種現象,如下

Original Table

這時如果你想要將 prefer_thing 欄位資料展開,以下提供兩個 function 幫助你垂直或水平展開欄位:

垂直展開

def flattenColumn(df, column):
"""
column is a string of the column's name.
for each value of the column's element (which might be a list),
duplicate the rest of columns at the corresponding row with the (each) value.
"""
column_flat = pd.DataFrame(
[
[i, c_flattened]
for i, y in df[column].apply(list).iteritems()
for c_flattened in y
],
columns=['I', column]
)
column_flat = column_flat.set_index('I')
return (
df.drop(column, 1)
.merge(column_flat, left_index=True, right_index=True)
)
Flatten column

水平展開

df = pd.DataFrame([pd.Series(x) for x in df.prefer_thing])
df.columns = ['team_{}'.format(x+1) for x in df.columns]

謝謝大家😱!!

--

--

Responses (1)