目錄
一、向量化與偽向量化
1、向量化
2、np.vectorize 偽向量化(特定場景)
3、apply(自定義函數)
二、apply函數
1、對series中使用apply
2、對dataframe中使用apply
3、apply函數案例-泰坦尼克號數據集]
數據集下載鏈接:
鏈接:https://pan.quark.cn/s/2598999d11dd?pwd=Xx7N
提取碼:Xx7N
一、向量化與偽向量化
????????在pandas中,向量化操作指的是直接在整個數組上執行操作,而不是循環遍歷每個元素,這些操作底層是由高效的c代碼實現的,并且利用了現代的cpu的SIMD指令(單指令多數據流),向量化操作在pandas和numpy中非常常見。
1、向量化
? ? ? ? (1)操作示例
import pandas as pd
df = pd.DataFrame({'A':[1,2,3], 'B':[4,5,6]]})
df['C'] = df['A'] + df['B'] # 列與列相加
df['D'] = df['A'] * 10 # 列乘以標量
df['E'] = np.log(df['A']) # 使用numpy的log函數作用于整列
? ? ? ? (2)向量化特點:
????????????????????????極高性能:比循環快100-1000倍
????????????????????????簡潔的語法:類似于數學公式的表達方式
????????????????????????廣泛的支持:數學、統計、字符串、日期等操作
2、np.vectorize 偽向量化(特定場景)
????????np.vectorize是一個將普通的python函數轉換成能夠處理numpy數組的函數(偽向量化函數),注意:它不是真正的向量化,底層仍然是循環遍歷每個元素,只是實現了一種方便的接口。可以使我們可以像向量化函數一樣去調用它。
????(1)np.vectorize 偽向量化特點:
????????????????偽向量化:內部仍然是python循環,僅提供了向量化接口
????????????????性能比純循環快2-5倍左右,但是比真正的向量化慢10-100倍
????????????????優勢在于簡化了代碼結構
? ? ? (2)使用場景:
????????????????場景1:當需要一個自定義標量函數應用到數組的每個元素,且該函數無法用pandas/numpy內置函數直接表示時。
? ? ? ? ? ? ? ? 例如:我們有一個復雜的函數,包含了多個條件的分支
def my_fun(x):
if x < 0:return 0
elif 0 <= x < 1:return x ** 2
else:return 2*x - 1# 使用np.vectorize
vfunc = np.vectorize(my_fun)# 應用在series
s = pd.Series([-0.5, 0.3, 0.9, 1.5, 2.0])
result = vfunc(s) # 返回:[0, 0.09, 0.81, 2.0, 3.0]
????????????????場景2:當函數有多個參數(其中有一些函數需要固定)時
def my_fun2(x, a, b):return a * x + b
# 需要固定a和b的值,只有x向量化
vfunc2 = np.vectorize(my_fun2, excluded=['a', 'b']))
3、apply(自定義函數)
apply()函數是pandas的方法,沿著dataFrame的軸(行或者列)應用自定義函數
? ? ? ? 特點:
? ? ? ? ? ? 靈活:既可以處理行又可以處理列
? ? ? ? ? ? 性能比較低:本質上是循環操作
性能:向量化函數>偽向量化函數>apply(自定義函數)
二、apply函數
????????apply函數是pandas中自由度(自定義)最高的函數之一,用來對series、dataframe或者分組對象應用自定義函數。
核心行為:
? ? 1:對series,逐個元素進行處理(輸入單個值,輸出單個值)
? ? 2:對dataframe,按照行(axis=1)或者列(axis=0)傳遞數據(輸入整行/整列數據,輸出結果)
? ? 3:對groupby對象,處理每個分組(輸入分組子集,輸出聚合結果)
核心作用:替代循環,實現批量處理,代碼簡介高效。
特點:逐行處理
1、對series中使用apply
需求:自定義函數my_fun1(),實現接受series對象,然后將接收到的每一個元素,計算其平方結果
def my_fun1(x):return x ** 2s = pd.Series([1,2,3,4])
r1 = s.apply(my_fun1)
print(r1)
輸出結果:
0???? 1
1???? 4
2???? 9
3??? 16
dtype: int64
需求:自定義函數my_fun2(),接受傳入參數的函數,例如:my_fun2(x, e)
def my_fun2(x, e):return x ** er2 = s.apply(my_fun2, e=3)
print(r2)
0 ? ? 1
1 ? ? 8
2 ? ?27
3 ? ?64
dtype: int64
2、對dataframe中使用apply
????????series的apply函數調用自定義函數,自定義函數接收到是數組中的每個元素,df接收到的是一整行或者整列
#1:創建df對象,創建兩個列
df = pd.DataFrame({'a':[10,20,30], 'b': [20,30,40]})
print(df.head())# 2:創建自定義函數my_fun3(), 作用于df對象
def my_fun3(x):print(f"x的內容:\n{x}")print(f"x的類型:{type(x)}")# 直接調用上述的my_fun3(),作用于df對象
# 不需要接受返回值輸出,因為這個自定義函數沒有返回值
df.apply(my_fun3) # 默認是按照列輸出
df.apply(my_fun3, axis=0) # axis值為0,就是按照列輸出
df.apply(my_fun3, axis=1) # axis值為1,就是按照行輸出
3、apply函數案例-泰坦尼克號數據集
import pandas as pd
df = pd.read_csv("data/titanic_train.csv")# 需求1:自定義函數,分別計算泰坦尼克號數據集某列的缺失值的個數,某列的缺失值占比,某列的非缺失值占比
# pd.isnull
def count_missing(vec):# vec就是接受到dfs對象的某列或者某行數據(要么是一整行數據要么是一整列數據)return pd.isnull(vec).sum() # 對傳入的一整行或者一整列,計算缺失值的數量# 某列的缺失值占比
def prop_missing(vec):# 缺失值的占比公式:某列的缺失值數量/某列的元素的總個數return pd.isnull(vec).sum() / vec.size# 某列的非缺失值占比
def prop_complete(vec):return 1-prop_missing(vec)# 測試上面的函數
# 默認:axis=0, 即:以列的方式傳入的
print(f"以列的形式傳入,計算某列的缺失值個數:\n{df.apply(count_missing)}") # 計算的是所有的列,沒有指定某個列,所有列中缺失值的數量
print(f"以列的形式傳入,計算某列的缺失值占比:\n{df.apply(prop_missing)}")
print(f"以列的形式傳入,計算某列的非缺失值占比:\n{df.apply(prop_complete)}")# 默認:axis=1, 即:以行的方式傳入的
print(f"以行的形式傳入,計算某行的缺失值個數:\n{df.apply(count_missing, axis=1)}") # 計算的是所有的列,沒有指定某個列,所有列中缺失值的數量
print(f"以行的形式傳入,計算某列的缺失值占比:\n{df.apply(prop_missing, axis=1)}")
print(f"以行的形式傳入,計算某列的非缺失值占比:\n{df.apply(prop_complete, axis=1)}")
計算某列的缺失值個數:PassengerId ? ? ?0
Survived ? ? ? ? 0
Pclass ? ? ? ? ? 0
Name ? ? ? ? ? ? 0
Sex ? ? ? ? ? ? ?0
Age ? ? ? ? ? ?177
SibSp ? ? ? ? ? ?0
Parch ? ? ? ? ? ?0
Ticket ? ? ? ? ? 0
Fare ? ? ? ? ? ? 0
Cabin ? ? ? ? ?687
Embarked ? ? ? ? 2
dtype: int64計算某列的缺失值占比:PassengerId ? ?0.000000
Survived ? ? ? 0.000000
Pclass ? ? ? ? 0.000000
Name ? ? ? ? ? 0.000000
Sex ? ? ? ? ? ?0.000000
Age ? ? ? ? ? ?0.198653
SibSp ? ? ? ? ?0.000000
Parch ? ? ? ? ?0.000000
Ticket ? ? ? ? 0.000000
Fare ? ? ? ? ? 0.000000
Cabin ? ? ? ? ?0.771044Embarked ? ? ? 0.002245
dtype: float64
計算某列的非缺失值占比:PassengerId ? ?1.000000
Survived ? ? ? 1.000000
Pclass ? ? ? ? 1.000000
Name ? ? ? ? ? 1.000000
Sex ? ? ? ? ? ?1.000000
Age ? ? ? ? ? ?0.801347
SibSp ? ? ? ? ?1.000000
Parch ? ? ? ? ?1.000000
Ticket ? ? ? ? 1.000000
Fare ? ? ? ? ? 1.000000
Cabin ? ? ? ? ?0.228956
Embarked ? ? ? 0.997755
dtype: float64