1. 程式人生 > 實用技巧 >Pandas 中的遍歷與並行處理

Pandas 中的遍歷與並行處理

使用 pandas 處理資料時,遍歷和並行處理是比較常見的操作了本文總結了幾種不同樣式的操作和並行處理方法。

1. 準備示例資料

import pandas as pd
import numpy as np

df = pd.DataFrame(np.random.randint(40, 100, (5, 10)), columns=[f's{i}' for i in range(10)], index=['john', 'bob', 'mike', 'bill', 'lisa'])
df['is_passed'] = df.s9.map(lambda x: True if x > 60 else False)

df 輸出:

      s0  s1  s2  s3  s4  s5  s6  s7  s8  s9  is_passed
john  56  70  85  91  92  80  63  81  45  57      False
bob   99  93  80  42  91  81  53  75  61  78       True
mike  76  92  76  80  57  98  94  79  87  94       True
bill  81  83  92  91  51  55  40  77  96  90       True
lisa  85  82  56  57  54  56  49  43  99  51      False

2. 遍歷

pandas 中,共有三種遍歷資料的方法,分別是:

2.1. iterrows

按行遍歷,將 DataFrame 的每一行迭代為 (index, Series) 對,可以通過 row[name]row.name 對元素進行訪問。

>>> for index, row in df.iterrows():
...     print(row['s0'])  # 也可使用 row.s0
    
56
99
76
81
85

2.2. itertuples

按行遍歷,將 DataFrame 的每一行迭代為命名元祖,可以通過 row.name 對元素進行訪問,比 iterrows

效率高。

>>> for row in df.itertuples():
...     print(row.s0)
    
56
99
76
81
85

2.3. iteritems

按列遍歷,將 DataFrame 的每一列迭代為 (列名, Series) 對,可以通過 row[index] 對元素進行訪問。

>>> for index, row in df.iteritems():
...     print(row[0])
    
56
70
85
91
92
80
63
81
45
57
False

3. 並行處理

3.1. map 方法

類似 Python 內建的 map() 方法,pandas 中的 map() 方法將函式、字典索引或是一些需要接受單個輸入值的特別的物件與對應的單個列的每一個元素建立聯絡並序列得到結果。map() 還有一個引數 na_action,類似 R 中的 na.action,取值為 None(預設) 或 ingore,用於控制遇到缺失值的處理方式,設定為 ingore 時序列運算過程中將忽略 Nan 值原樣返回。

比如這裡將 is_passed 列中的 True 換為 1False 換位 0,可以有下面幾種實現方式:

3.1.1. 字典對映

>>> # 定義對映字典
... score_map = {True: 1, False: 0}

>>> # 利用 map() 方法得到對應 mike 列的對映列
... df.is_passed.map(score_map)

john    0
bob     1
mike    1
bill    1
lisa    0
Name: is_passed, dtype: int64

3.1.2. lambda 函式

>>> # 如同建立該列時的那樣
... df.is_passed.map(lambda x: 1 if x else 0)

john    0
bob     1
mike    1
bill    1
lisa    0
Name: is_passed, dtype: int64

3.1.3. 常規函式

>>> def bool_to_num(x):
...     return 1 if x else 0

>>> df.is_passed.map(bool_to_num)

3.1.4. 特殊物件

一些接收單個輸入值且有輸出的物件也可以用map()方法來處理:

>>> df.is_passed.map('is passed: {}'.format)

john    is passed: False
bob      is passed: True
mike     is passed: True
bill     is passed: True
lisa    is passed: False
Name: is_passed, dtype: object

3.2. apply 方法

apply() 使用方式跟 map() 很像,主要傳入的主要引數都是接受輸入返回輸出,但相較於 map() 針對單列 Series 進行處理,一條 apply() 語句可以對單列或多列進行運算,覆蓋非常多的使用場景,下面分別介紹:

3.2.1. 單列資料

傳入 lambda 函式:

df.is_passed.apply(lambda x: 1 if x else 0)

3.2.2. 輸入多列資料

>>> def gen_describe(s9, is_passed):
...     return f"s9's score is {s9}, so {'passed' if is_passed else 'failed'}"

>>> df.apply(lambda r: gen_describe(r['s9'], r['is_passed']), axis=1)

john    s9's score is 57, so failed
bob     s9's score is 78, so passed
mike    s9's score is 94, so passed
bill    s9's score is 90, so passed
lisa    s9's score is 51, so failed
dtype: object

3.2.3. 輸出多列資料

>>> df.apply(lambda row: (row['s9'], row['s8']), axis=1)

john    (57, 45)
bob     (78, 61)
mike    (94, 87)
bill    (90, 96)
lisa    (51, 99)
dtype: object

3.3. applymap 方法

applymap 是與 map 方法相對應的專屬於 DataFrame 物件的方法,類似 map 方法傳入函式、字典等,傳入對應的輸出結果,
不同的是 applymap 將傳入的函式等作用於整個資料框中每一個位置的元素,比如將 df 中的所有小於 50 的全部改為 50

>>> def at_least_get_50(x):
...     if isinstance(x, int) and x < 50:
...         return 50
...     return x

>>> df.applymap(at_least_get_50)

      s0  s1  s2  s3  s4  s5  s6  s7  s8  s9  is_passed
john  56  70  85  91  92  80  63  81  50  57      False
bob   99  93  80  50  91  81  53  75  61  78       True
mike  76  92  76  80  57  98  94  79  87  94       True
bill  81  83  92  91  51  55  50  77  96  90       True
lisa  85  82  56  57  54  56  50  50  99  51      False

附:結合 tqdm 給 apply 過程新增進度條

jupyter 中並行處理較大資料量的時候,往往執行後就只能乾等著報錯或者執行完了,使用 tqdm 可以檢視資料實時處理進度,使用前需使用 pip install tqdm 安裝該包。使用示例如下:

from tqdm import tqdm

def gen_describe(s9, is_passed):
    return f"s9's score is {s9}, so {'passed' if is_passed else 'failed'}"

#啟動對緊跟著的 apply 過程的監視
tqdm.pandas(desc='apply')
df.progress_apply(lambda r: gen_describe(r['s9'], r['is_passed']), axis=1)

參考

  1. (資料科學學習手札69)詳解pandas中的map、apply、applymap、groupby、agg