您好,登錄后才能下訂單哦!
這篇文章主要講解了“怎么使用pandas apply()函數”,文中的講解內容簡單清晰,易于學習與理解,下面請大家跟著小編的思路慢慢深入,一起來研究和學習“怎么使用pandas apply()函數”吧!
理解 pandas 的函數,要對函數式編程有一定的概念和理解。函數式編程,包括函數式編程思維,當然是一個很復雜的話題,但對今天介紹的 apply()
函數,只需要理解:函數作為一個對象,能作為參數傳遞給其它函數,也能作為函數的返回值。
函數作為對象能帶來代碼風格的巨大改變。舉一個例子,有一個類型為 list 的變量,包含 從 1 到 10 的數據,需要從其中找出能被 3 整除的所有數字。用傳統的方法:
def can_divide_by_three(number): if number % 3 == 0: return True else: return False selected_numbers = [] for number in range(1, 11): if can_divide_by_three(number): selected_numbers.append(number)
循環是不可少的,因為 can_divide_by_three()
函數只用一次,考慮用 lambda 表達式簡化:
divide_by_three = lambda x : True if x % 3 == 0 else False selected_numbers = [] for number in range(1, 11): if divide_by_three(item): selected_numbers.append(item)
以上是傳統編程思維方式,而函數式編程思維則完全不同。我們可以這樣想:從 list 中取出特定規則的數字,能不能只關注和設置規則,循環這種事情交給編程語言去處理呢?當然可以。當編程人員只關心規則(規則可能是一個條件,或者由某一個 function 來定義),代碼將大大簡化,可讀性也更強。
Python 語言提供 filter()
函數,語法如下:
filter(function, sequence)
filter()
函數的功能:對 sequence 中的 item 依次執行 function(item),將結果為 True 的 item 組成一個 List/String/Tuple(取決于 sequence 的類型)并返回。有了這個函數,上面的代碼可以簡化為:
divide_by_three = lambda x : True if x % 3 == 0 else False selected_numbers = filter(divide_by_three, range(1, 11))
將 lambda 表達式放在語句中,代碼簡化到只需要一句話就夠了:
selected_numbers = filter(lambda x: x % 3 == 0, range(1, 11))
回到主題, pandas 的 apply()
函數可以作用于 Series
或者整個 DataFrame
,功能也是自動遍歷整個 Series
或者 DataFrame
, 對每一個元素運行指定的函數。
舉一個例子,現在有這樣一組數據,學生的考試成績:
Name Nationality Score 張 漢 400 李 回 450 王 漢 460
如果民族不是漢族,則總分在考試分數上再加 5 分,現在需要用 pandas 來做這種計算,我們在 Dataframe 中增加一列。當然如果只是為了得到結果, numpy.where()
函數更簡單,這里主要為了演示 Series.apply()
函數的用法。
import pandas as pd df = pd.read_csv("studuent-score.csv") df['ExtraScore'] = df['Nationality'].apply(lambda x : 5 if x != '漢' else 0) df['TotalScore'] = df['Score'] + df['ExtraScore']
對于 Nationality 這一列, pandas 遍歷每一個值,并且對這個值執行 lambda 匿名函數,將計算結果存儲在一個新的 Series
中返回。上面代碼在 jupyter notebook 中顯示的結果如下:
Name Nationality Score ExtraScore TotalScore
0 張 漢 400 0 400
1 李 回 450 5 455
2 王 漢 460 0 460
apply()
函數當然也可執行 python 內置的函數,比如我們想得到 Name 這一列字符的個數,如果用 apply()
的話:
df['NameLength'] = df['Name'].apply(len)
根據 pandas 幫助文檔 pandas.Series.apply — pandas 1.3.1 documentation,該函數可以接收位置參數或者關鍵字參數,語法如下:
Series.apply(func, convert_dtype=True, args=(), **kwargs)
對于 func 參數來說,該函數定義中的第一個參數是必須的,所以 funct() 除第一個參數之外的其它參數則被視為額外的參數,作為參數來傳遞。我們仍以剛才的示例進行說明,假設除漢族外,其他少數名族有加分,我們把加分放在函數的參數中,先定義一個 add_extra() 函數:
def add_extra(nationality, extra): if nationality != "漢": return extra else: return 0
對 df 新增一列:
df['ExtraScore'] = df.Nationality.apply(add_extra, args=(5,))
位置參數通過 args = () 來傳遞參數,類型為 tuple。也可用下面的方法調用:
df['ExtraScore'] = df.Nationality.apply(add_extra, extra=5)
運行后結果為:
Name Nationality Score ExtraScore
0 張 漢 400 0
1 李 回 450 5
2 王 漢 460 0
將 add_extra 作為 lambda 函數:
df['Extra'] = df.Nationality.apply(lambda n, extra : extra if n == '漢' else 0, args=(5,))
下面繼續講解關鍵字參數。假設我們對不同的民族可以給不同的加分,定義 add_extra2() 函數:
def add_extra2(nationaltiy, **kwargs): return kwargs[nationaltiy] df['Extra'] = df.Nationality.apply(add_extra2, 漢=0, 回=10, 藏=5)
運行結果為:
Name Nationality Score Extra
0 張 漢 400 0
1 李 回 450 10
2 王 漢 460 0
對照 apply 函數的語法,不難理解。
DataFrame.apply()
函數則會遍歷每一個元素,對元素運行指定的 function。比如下面的示例:
import pandas as pd import numpy as np matrix = [ [1,2,3], [4,5,6], [7,8,9] ] df = pd.DataFrame(matrix, columns=list('xyz'), index=list('abc')) df.apply(np.square)
對 df 執行 square()
函數后,所有的元素都執行平方運算:
x y z a 1 4 9 b 16 25 36 c 49 64 81
如果只想 apply()
作用于指定的行和列,可以用行或者列的 name
屬性進行限定。比如下面的示例將 x 列進行平方運算:
df.apply(lambda x : np.square(x) if x.name=='x' else x)
x y z a 1 2 3 b 16 5 6 c 49 8 9
下面的示例對 x 和 y 列進行平方運算:
df.apply(lambda x : np.square(x) if x.name in ['x', 'y'] else x)
x y z a 1 4 3 b 16 25 6 c 49 64 9
下面的示例對第一行 (a 標簽所在行)進行平方運算:
df.apply(lambda x : np.square(x) if x.name == 'a' else x, axis=1)
默認情況下 axis=0
表示按列,axis=1
表示按行。
平時我們會經常用到日期的計算,比如要計算兩個日期的間隔,比如下面的一組關于 wbs 起止日期的數據:
wbs date_from date_to job1 2019-04-01 2019-05-01 job2 2019-04-07 2019-05-17 job3 2019-05-16 2019-05-31 job4 2019-05-20 2019-06-11
假定要計算起止日期間隔的天數。比較簡單的方法就是兩列相減(datetime 類型):
import pandas as pd import datetime as dt wbs = { "wbs": ["job1", "job2", "job3", "job4"], "date_from": ["2019-04-01", "2019-04-07", "2019-05-16","2019-05-20"], "date_to": ["2019-05-01", "2019-05-17", "2019-05-31", "2019-06-11"] } df = pd.DataFrame(wbs) df['elpased'] = df['date_to'].apply(pd.to_datetime) - df['date_from'].apply(pd.to_datetime)
apply()
函數將 date_from
和 date_to
兩列轉換成 datetime 類型。我們 print 一下 df:
wbs date_from date_to elapsed 0 job1 2019-04-01 2019-05-01 30 days 1 job2 2019-04-07 2019-05-17 40 days 2 job3 2019-05-16 2019-05-31 15 days 3 job4 2019-05-20 2019-06-11 22 days
日期間隔已經計算出來,但后面帶有一個單位 days,這是因為兩個 datetime
類型相減,得到的數據類型是 timedelta64
,如果只要數字,還需要使用 timedelta
的 days
屬性轉換一下。
elapsed= df['date_to'].apply(pd.to_datetime) - df['date_from'].apply(pd.to_datetime) df['elapsed'] = elapsed.apply(lambda x : x.days)
使用 DataFrame.apply()
函數也能達到同樣的效果,我們需要先定義一個函數 get_interval_days()
函數的第一列是一個 Series
類型的變量,執行的時候,依次接收 DataFrame 的每一行。
import pandas as pd import datetime as dt def get_interval_days(arrLike, start, end): start_date = dt.datetime.strptime(arrLike[start], '%Y-%m-%d') end_date = dt.datetime.strptime(arrLike[end], '%Y-%m-%d') return (end_date - start_date).days wbs = { "wbs": ["job1", "job2", "job3", "job4"], "date_from": ["2019-04-01", "2019-04-07", "2019-05-16","2019-05-20"], "date_to": ["2019-05-01", "2019-05-17", "2019-05-31", "2019-06-11"] } df = pd.DataFrame(wbs) df['elapsed'] = df.apply( get_interval_days, axis=1, args=('date_from', 'date_to'))
感謝各位的閱讀,以上就是“怎么使用pandas apply()函數”的內容了,經過本文的學習后,相信大家對怎么使用pandas apply()函數這一問題有了更深刻的體會,具體使用情況還需要大家實踐驗證。這里是億速云,小編將為大家推送更多相關知識點的文章,歡迎關注!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。