1 lambda
lambda原型為:lambda 參數:操作(參數)
lambda函數也叫匿名函數,即沒有具體名稱的函數,它允許快速定義單行函數,可以用在任何需要函數的地方。這區別於def定義的函數。
lambda與def的區別:
1)def創建的方法是有名稱的,而lambda沒有。
2)lambda會返回一個函數對象,但這個對象不會賦給一個標識符,而def則會把函數對象賦值給一個變量(函數名)。
3)lambda只是一個表達式,而def則是一個語句。
4)lambda表達式” : “后面,只能有一個表達式,def則可以有多個。
5)像if或for或print等語句不能用於lambda中,def可以。
6)lambda一般用來定義簡單的函數,而def可以定義復雜的函數。
1.1 舉最簡單的例子
#單個參數的:
g = lambda x : x ** 2
print g(3)
9
#多個參數的:
g = lambda x, y, z : (x + y) ** z
print g(1,2,2)
9
1.2 再舉一個普通的例子
將一個 list 里的每個元素都平方:
map( lambda x: x*x, [y for y in range(10)] )
這個寫法要好過
def sq(x):
return x * x
map(sq, [y for y in range(10)])
因為后者多定義了一個(污染環境的)函數,尤其如果這個函數只會使用一次的話。
進一步講,匿名函數本質上就是一個函數,它所抽象出來的東西是一組運算。這是什么意思呢?類比
a = [1, 2, 3]
和
f = lambda x : x + 1
我們會發現,等號右邊的東西完全可以脫離等號左邊的東西而存在,等號左邊的名字只是右邊之實體的標識符。如果能習慣 [1, 2, 3] 單獨存在,那么 lambda x : x + 1 也能單獨存在其實也就不難理解了,它的意義就是給「某個數加一」這一運算本身。
現在回頭來看 map() 函數,它可以將一個函數映射到一個可枚舉類型上面。沿用上面給出的 a 和 f,可以寫
map(f, a)
也就是將函數 f 依次套用在 a 的每一個元素上面,獲得結果 [2, 3, 4]。現在用 lambda 表達式來替換 f,就變成:
map( lambda x : x + 1, [1, 2, 3] )
會不會覺得現在很一目了然了?尤其是類比
a = [1, 2, 3]
r = []
for each in a:
r.append(each+1)
2 Apply
Python中apply函數的格式為:apply(func,*args,**kwargs)
當然,func可以是匿名函數。
用途:當一個函數的參數存在於一個元組或者一個字典中時,用來間接的調用這個函數,並將元組或者字典中的參數按照順序傳遞給參數
解析:args是一個包含按照函數所需參數傳遞的位置參數的一個元組,簡單來說,假如A函數的函數位置為 A(a=1,b=2),那么這個元組中就必須嚴格按照這個參數的位置順序進行傳遞(a=3,b=4),而不能是(b=4,a=3)這樣的順序。kwargs是一個包含關鍵字參數的字典,而其中args如果不傳遞,kwargs需要傳遞,則必須在args的位置留空。
apply的返回值就是函數func函數的返回值。
2.1 舉例
def function(a,b):
print(a,b)
apply(function,('good','better'))
apply(function,(2,3+6))
apply(function,('cai','quan'))
apply(function,('cai',),{'b':'caiquan'})
apply(function,(),{'a':'caiquan','b':'Tom'})
輸出結果:
('good', 'better')
(2, 9)
('cai', 'quan')
('cai', 'caiquan')
('caiquan', 'Tom')
有時候,函數的參數可能是DataFrame中的行或者列。
2.2 下面的例子是DataFrame中apply的用法
函數應用和映射
import numpy as np
import pandas as pd
df=pd.DataFrame(np.random.randn(4,3),columns=list('bde'),index=['utah','ohio','texas','oregon'])
print(df)
b d e
utah -0.667969 1.974801 0.738890
ohio -0.896774 -0.790914 0.474183
texas 0.043476 0.890176 -0.662676
oregon 0.701109 -2.238288 -0.154442
將函數應用到由各列或行形成的一維數組上。DataFrame的apply方法可以實現此功能
f=lambda x:x.max()-x.min()
默認情況下會以列為單位,分別對列應用函數
t1=df.apply(f)
print(t1)
t2=df.apply(f,axis=1)
print(t2)
b 1.597883
d 4.213089
e 1.401566
dtype: float64
utah 2.642770
ohio 1.370957
texas 1.552852
oregon 2.939397
dtype: float64
除標量外,傳遞給apply的函數還可以返回由多個值組成的Series
def f(x):
return pd.Series([x.min(),x.max()],index=['min','max'])
t3=df.apply(f)
從運行的結果可以看出,按列調用的順序,調用函數運行的結果在右邊依次追加
print(t3)
b d e
min -0.896774 -2.238288 -0.662676
max 0.701109 1.974801 0.738890
元素級的python函數,將函數應用到每一個元素
將DataFrame中的各個浮點值保留兩位小數
f=lambda x: '%.2f'%x
t3=df.applymap(f)
print(t3)
b d e
utah -0.67 1.97 0.74
ohio -0.90 -0.79 0.47
texas 0.04 0.89 -0.66
oregon 0.70 -2.24 -0.15
注意,之所以這里用map,是因為Series有一個元素級函數的map方法。而dataframe只有applymap。
t4=df['e'].map(f)
print(t4)
utah 0.74
ohio 0.47
texas -0.66
oregon -0.15
小技巧:
1, 有一個 pandas.DataFrame df, 有ABCD四列,其中AB是索引列,C列的數據是str,部分前后有空格,現在用一段代碼將C列數據上的空格刪除
lam = lambda x:x.strip()
df['C']=df['C'].apply(lam)
2,pandas-如何得到某一個值所在的行
df[df['列名'].isin([相應的值])]
其它例子
試圖根據像這樣的數據框中的人的大小來推斷分類:
Size
1 80000
2 8000000
3 8000000000
希望它看起來像這樣:
Size Classification
1 80000 <1m
2 8000000 1-10m
3 8000000000 >1bi
理想的過程是應用這樣的lambda函數:
df['Classification']=df['Size'].apply(lambda x: "<1m" if x<1000000 else "1-10m" if 1000000<x<10000000 else ...)
檢查了幾個關於lambda函數中的多個ifs的帖子,here is an example link,但是這個synthax在多個ifs語句中由於某種原因不適合我,但是它在單個if條件下工作.
所以我嘗試了這個“非常優雅”的解決方案:
df['Classification']=df['Size'].apply(lambda x: "<1m" if x<1000000 else pass)
df['Classification']=df['Size'].apply(lambda x: "1-10m" if 1000000 < x < 10000000 else pass)
df['Classification']=df['Size'].apply(lambda x: "10-50m" if 10000000 < x < 50000000 else pass)
df['Classification']=df['Size'].apply(lambda x: "50-100m" if 50000000 < x < 100000000 else pass)
df['Classification']=df['Size'].apply(lambda x: "100-500m" if 100000000 < x < 500000000 else pass)
df['Classification']=df['Size'].apply(lambda x: "500m-1bi" if 500000000 < x < 1000000000 else pass)
df['Classification']=df['Size'].apply(lambda x: ">1bi" if 1000000000 < x else pass)
可以看出“pass”似乎也不適用於lambda函數:
df['Classification']=df['Size'].apply(lambda x: "<1m" if x<1000000 else pass)
SyntaxError: invalid syntax
關於Pandas中apply方法中lambda函數內多個if語句的正確synthax的任何建議?多線或單線解決方案對我有用.
這是一個可以構建的小例子:
基本上,lambda x:x ..是函數的短單行.真正需要的是一個你可以輕松重建的功能.
import pandas as pd
# Recreate the dataframe
data = dict(Size=[80000,8000000,800000000])
df = pd.DataFrame(data)
# Create a function that returns desired values
# You only need to check upper bound as the next elif-statement will catch the value
def func(x):
if x < 1e6:
return "<1m"
elif x < 1e7:
return "1-10m"
elif x < 5e7:
return "10-50m"
else:
return 'N/A'
# Add elif statements....
df['Classification'] = df['Size'].apply(func)
print(df)
返回:
Size Classification
0 80000 <1m
1 8000000 1-10m
2 800000000 N/A
3 參考文獻
【1】Lambda 表達式有何用處?如何使用?
https://www.zhihu.com/question/20125256
【2】python DataFrame的apply方法
https://blog.csdn.net/u013385362/article/details/79155573
【3】pandas官方文檔
https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.apply.html