Pandas教程 | 數據處理三板斧——map、apply、applymap詳解


在日常的數據處理中,經常會對一個DataFrame進行逐行、逐列和逐元素的操作,對應這些操作,Pandas中的mapapplyapplymap可以解決絕大部分這樣的數據處理需求。這篇文章就以案例附帶圖解的方式,為大家詳細介紹一下這三個方法的實現原理,相信讀完本文后,不論是小白還是Pandas的進階學習者,都會對這三個方法有更深入的理解。

本文演示的數據集是模擬生成的,想練手的可以按下方的代碼生成。

boolean=[True,False]
gender=["",""]
color=["white","black","yellow"]
data=pd.DataFrame({
    "height":np.random.randint(150,190,100),
    "weight":np.random.randint(40,90,100),
    "smoker":[boolean[x] for x in np.random.randint(0,2,100)],
    "gender":[gender[x] for x in np.random.randint(0,2,100)],
    "age":np.random.randint(15,90,100),
    "color":[color[x] for x in np.random.randint(0,len(color),100) ]
}
)

 

數據集如下所示,各列分別代表身高、體重、是否吸煙、性別、年齡和膚色。

Series數據處理

1. map用法

如果需要把數據集中gender列的男替換為1,女替換為0,怎么做呢?絕對不是用for循環實現,使用Series.map()可以很容易做到,最少僅需一行代碼。

#①使用字典進行映射
data["gender"] = data["gender"].map({"":1, "":0})

​
#②使用函數
def gender_map(x):
    gender = 1 if x == "" else 0
    return gender
#注意這里傳入的是函數名,不帶括號
data["gender"] = data["gender"].map(gender_map)
 

map在實際過程中是怎么運行的呢?請看下面的圖解(為了方便展示,僅截取了前10條數據)

不論是利用字典還是函數進行映射,map方法都是把對應的數據逐個當作參數傳入到字典或函數中,得到映射后的值。

2. apply

同時Series對象還有apply方法,apply方法的作用原理和map方法類似,區別在於apply能夠傳入功能更為復雜的函數。怎么理解呢?一起看看下面的例子。

假設在數據統計的過程中,年齡age列有較大誤差,需要對其進行調整(加上或減去一個值),由於這個加上或減去的值未知,故在定義函數時,需要加多一個參數bias,此時用map方法是操作不了的(傳入map的函數只能接收一個參數),apply方法則可以解決這個問題。

def apply_age(x,bias):
    return x+bias

#以元組的方式傳入額外的參數
data["age"] = data["age"].apply(apply_age,args=(-3,))
 

可以看到age列都減了3,當然,這里只是簡單舉了個例子,當需要進行復雜處理時,更能體現apply的作用。

總而言之,對於Series而言,map可以解決絕大多數的數據處理需求,但如果需要使用較為復雜的函數,則需要用到apply方法。

DataFrame數據處理

1. apply

DataFrame而言,apply是非常重要的數據處理方法,它可以接收各種各樣的函數(Python內置的或自定義的),處理方式很靈活,下面通過幾個例子來看看apply的具體使用及其原理。

在進行具體介紹之前,首先需要介紹一下DataFrameaxis的概念,在DataFrame對象的大多數方法中,都會有axis這個參數,它控制了你指定的操作是沿着0軸還是1軸進行。axis=0代表操作對列columns進行,axis=1代表操作對行row進行,如下圖所示。

如果還不是很了解,沒關系,下面會分別對apply沿着0軸以及1軸的操作進行講解,繼續往下走。

假設現在需要對data中的數值列分別進行取對數和求和的操作,這時可以用apply進行相應的操作,因為是對列進行操作,所以需要指定axis=0,使用下面的兩行代碼可以很輕松地解決我們的問題。

# 沿着0軸求和
data[["height","weight","age"]].apply(np.sum, axis=0)
​
# 沿着0軸取對數
data[["height","weight","age"]].apply(np.log, axis=0)

 

實現的方式很簡單,但調用apply時究竟發生了什么呢?過程是怎么實現的?還是通過圖解的方式來一探究竟。(取前五條數據為例)

 

當沿着軸0(axis=0)進行操作時,會將各列(columns)默認以Series的形式作為參數,傳入到你指定的操作函數中,操作后合並並返回相應的結果。

那如果在實際使用中需要按行進行操作(axis=1),那整個過程又是怎么實現的呢?

在數據集中,有身高和體重的數據,所以根據這個,我們可以計算每個人的BMI指數(體檢時常用的指標,衡量人體肥胖程度和是否健康的重要標准),計算公式是:體重指數BMI=體重/身高的平方(國際單位kg/㎡),因為需要對每個樣本進行操作,這里使用axis=1apply進行操作,代碼如下:

def BMI(series):
    weight = series["weight"]
    height = series["height"]/100
    BMI = weight/height**2
    return BMI
​
data["BMI"] = data.apply(BMI,axis=1)

 

還是用圖解的方式來看看這個過程到底是怎么實現的(以前5條數據為例)。

apply設置了axis=1對行進行操作時,會默認將每一行數據以Series的形式(Series的索引為列名)傳入指定函數,返回相應的結果。

總結一下對DataFrameapply操作:

  1. axis=0時,對每列columns執行指定函數;當axis=1時,對每行row執行指定函數。
  2. 無論axis=0還是axis=1,其傳入指定函數的默認形式均為Series,可以通過設置raw=True傳入numpy數組
  3. 對每個Series執行結果后,會將結果整合在一起返回(若想有返回值,定義函數時需要return相應的值)
  4. 當然,DataFrameapplySeriesapply一樣,也能接收更復雜的函數,如傳入參數等,實現原理是一樣的,具體用法詳見官方文檔。

2. applymap

applymap的用法比較簡單,會對DataFrame中的每個單元格執行指定函數的操作,雖然用途不如apply廣泛,但在某些場合下還是比較有用的,如下面這個例子。

為了演示的方便,新生成一個DataFrame

df = pd.DataFrame(
    {
        "A":np.random.randn(5),
        "B":np.random.randn(5),
        "C":np.random.randn(5),
        "D":np.random.randn(5),
        "E":np.random.randn(5),
    }
)
df

 

 

 

現在想將DataFrame中所有的值保留兩位小數顯示,使用applymap可以很快達到你想要的目的,代碼和圖解如下:

df.applymap(lambda x:"%.2f" % x)

 

相關文章:

  1. Pandas數據分析——超好用的Groupby詳解
  2. Pandas數據分析——Merge數據拼接圖文詳解
  3. Pandas數據處理——玩轉時間序列數據
  4. Pandas數據處理——盤點那些常用的函數(上)
  5. Pandas數據處理——盤點那些常用的函數(下)
  6. 天秀!Pandas還能用來寫爬蟲?
  7. 提高數據的顏值!一起看看Pandas中的那些Style
  8. 提速百倍的Pandas性能優化方法,讓你的Pandas飛起來!

 轉自https://zhuanlan.zhihu.com/p/100064394


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM