Pandas 數(shù)據(jù)類型操作
本文總結(jié)了 Pandas 中進(jìn)行數(shù)據(jù)類型轉(zhuǎn)換的三種基本方法,同時介紹了基于數(shù)據(jù)類型取數(shù)的方法:
使用 astype() 函數(shù)進(jìn)行強(qiáng)制類型轉(zhuǎn)換 通過自定義函數(shù)來進(jìn)行數(shù)據(jù)類型轉(zhuǎn)換 使用 Pandas 提供的函數(shù)如 to_numeric()、to_datetime() 等進(jìn)行轉(zhuǎn)化 select_dtypes 函數(shù)的使用
一、Pandas、Python、Numpy 各自支持的數(shù)據(jù)類型
下表中展示的是 Pandas、Python 和 Numpy 中支持的數(shù)據(jù)類型,可以看到 pandas中支持的類型是最豐富的。

二、模擬數(shù)據(jù)
2.1 導(dǎo)入數(shù)據(jù)
下面是模擬的一份數(shù)據(jù),包含多個字段名稱

import pandas as pd
import numpy as np
# 讀取數(shù)據(jù)
df = pd.read_csv("數(shù)據(jù)類型操作.csv")
df

2.2 數(shù)據(jù)類型查看
查看數(shù)據(jù)的字段類型:

df.dtypes # 各字段的數(shù)據(jù)類型
df.team.dtype # 某個字段的類型
s.dtype # Series 的類型
df.dtypes.value_counts() # 各類型有多少個字段
三、實(shí)際案例
3.1 字符型轉(zhuǎn)成數(shù)值型
比如我們想在數(shù)據(jù)上進(jìn)行一些操作,比如將"2019年"、和"2020年"的數(shù)據(jù)相加:很明顯數(shù)據(jù)不是我們想要的結(jié)果。
根本原因:這兩個字段是字符類型,進(jìn)行+操作,是直接將里面的內(nèi)容拼接在一起,而不是里面數(shù)值的相加。

正確的操作:
1、先把這兩個字段中的數(shù)字單獨(dú)提取出來
# 分割之后取出第1個元素
df["2020年_新"] = df["2020年"].apply(lambda x:x.split("元")[0])
df["2019年_新"] = df["2019年"].apply(lambda x:x.split("元")[0])
df

2、查看數(shù)據(jù)類型
生成的兩個新字段仍然是字符類型,不能直接相加

3、將數(shù)字表現(xiàn)型的字符型數(shù)據(jù)轉(zhuǎn)成數(shù)值型
有兩種方法實(shí)現(xiàn)這種需求:
pd.astype("float") :指定類型 to_numeric():直接轉(zhuǎn)化
## 字符類型的數(shù)值轉(zhuǎn)成純數(shù)值型
# 等價寫法:df["2020年_新"] = df.astype({"2020年_新":"int") 字典形式傳入
df["2020年_新"] = df["2020年_新"].astype("int")
df['2019年_新'] = pd.to_numeric(df['2019年_新'], errors='coerce')
df

3、將兩個新的字段相加
df["前兩年之和"] = df["2020年_新"] + df["2019年_新"]
df

求兩個年份之間的差值:

3.2 數(shù)值型轉(zhuǎn)成字符型
求出 2020 年的增長率:
df["增長率"] = df["前兩年之差"] / df["2019年_新"]
df

現(xiàn)在整個增長率是 float 的數(shù)值型,我們想把它轉(zhuǎn)成 % 的形式,也就是字符類型的數(shù)據(jù):
顧客姓名 object
顧客編碼 int64
客戶部門 object
客戶組別 float64
2019年 object
2020年 object
日 int64
月 int64
年 int64
是否大客戶 object
2020年_新 int64
2019年_新 int64
前兩年之和 int64
前兩年之差 int64
增長率 float64 # 數(shù)值型數(shù)據(jù)
dtype: object
在這里也是兩種方法滿足上面的需求:
方法1:通過 str 函數(shù)的轉(zhuǎn)化 方法2:通過 format 函數(shù)的格式化輸出
df["增長率1"] = df["增長率"].apply(lambda x: str(round(100*x,2)) + "%")
df["增長率2"] = df["增長率"].apply(lambda x: format(x,'.2%'))
df

顧客姓名 object
顧客編碼 int64
客戶部門 object
客戶組別 float64
2019年 object
2020年 object
日 int64
月 int64
年 int64
是否大客戶 object
2020年_新 int64
2019年_新 int64
前兩年之和 int64
前兩年之差 int64
增長率 float64
增長率1 object # 兩個字符類型的數(shù)據(jù)
增長率2 object
dtype: object
3.3 數(shù)值型數(shù)據(jù)存在缺失值
如果某個字段中大部分的數(shù)據(jù)都是數(shù)值型,但是存在少量的缺失值的情況,可以使用下面的方法進(jìn)行轉(zhuǎn)化:

df["客戶組別"] = pd.to_numeric(df['客戶組別'], errors='coerce').fillna(0) # 未知的組用0代替;0可以換成其他數(shù)值
df

3.4 數(shù)值型類型轉(zhuǎn)成時間類型
如果在實(shí)際數(shù)據(jù)中,我們遇到類似年、月、日等時間的數(shù)據(jù),可以進(jìn)行轉(zhuǎn)化:比如我們想根據(jù)數(shù)據(jù)中的年月日生成一個生日的字段

1、上面的日、月、年現(xiàn)在是數(shù)值類型的數(shù)據(jù),不能直接相加,先進(jìn)行轉(zhuǎn)化:
df["月"] = df["月"].astype(str)
df["年"] = df["年"].astype(str)
2、轉(zhuǎn)成字符型數(shù)據(jù)之后,再進(jìn)行相加:
df["生日"] = df["年"] + "-" + df["月"] + "-" + df["日"]
df

3、通過 pd.to_datetime 轉(zhuǎn)成 pandas 中的時間類型數(shù)據(jù)
df["生日"] = df["生日"].apply(lambda x: pd.to_datetime(x,format="%Y-%m-%d"))
df.dtypes

經(jīng)過檢驗(yàn):如果字段是用英文表示的,下面的方法可以直接轉(zhuǎn)成datetime64[ns]類型,使用中文漢字當(dāng)做屬性名的時候,該方法不適用。
Pandas 中的 to_datetime() 函數(shù)可以把單獨(dú)的 year、month、day 三列合并成一個單獨(dú)的時間戳:
pd.to_datetime(df[['year', 'month', 'day']]) # 組合成日期


3.5 布爾值判斷使用
比如在是否為大客戶中,我們想將 Y 換成 True,N 換成 False,可以通過 np.where 來是實(shí)現(xiàn):
df["是否大客戶"] = np.where(df["是否大客戶"] == "Y", True, False)
df

3.6 讀取文件直接轉(zhuǎn)換
在使用 pandas 讀取文件的時候,可以直接改變數(shù)據(jù)類型,使用參數(shù)是 converters:
df0 = pd.read_csv("數(shù)據(jù)類型操作.csv",
converters={
"顧客編碼":str, # 指定改變的函數(shù)
"2019年":lambda x:float(x.split("元")[0]), # 切割函數(shù)
"2020年":lambda x:float(x.replace("元","")), # 替換函數(shù)
"客戶組別":lambda x: pd.to_numeric(x, errors='coerce'),
"是否大客戶":lambda x:np.where(x == "Y",True,False)
}
)
df0

四、根據(jù)數(shù)據(jù)類型取數(shù)
df 中的數(shù)據(jù)類型為:object、int64、float64、bool、datetime64[ns]
df.dtypes
# 結(jié)果
顧客姓名 object
顧客編碼 int64
客戶部門 object
客戶組別 float64
2019年 object
2020年 object
日 object
月 object
年 object
是否大客戶 bool
2020年_新 int64
2019年_新 int64
前兩年之和 int64
前兩年之差 int64
增長率 float64
增長率1 object
增長率2 object
生日 datetime64[ns]
dtype: object
4.1 包含數(shù)據(jù)類型
df.select_dtypes(include=["object"]) # 包含object類型的數(shù)據(jù)

也可以同時篩選包含多個數(shù)據(jù)類型:
df.select_dtypes(include=["object","bool"])

4.2 不包含數(shù)據(jù)類型
df.select_dtypes(exclude=["object"]) # 不包含object類型的數(shù)據(jù)

同時排除多個字段數(shù)據(jù)類型:
df.select_dtypes(exclude=["object","bool"]) # 兩個類型的數(shù)據(jù)同時排除

五、總結(jié)
對數(shù)據(jù)進(jìn)行操作的第一步就是保證我們設(shè)置了正確的數(shù)據(jù)類型,然后才能進(jìn)行后續(xù)的數(shù)據(jù)處理、數(shù)據(jù)分析、可視化等一系列的操作。不用的數(shù)據(jù)類型可以用不同的處理方法。
注意,一個列只能有一個總數(shù)據(jù)類型。本文中介紹了 Pandas 中常見的數(shù)據(jù)類型轉(zhuǎn)化和基于數(shù)據(jù)類型取數(shù)的方法,希望對讀者有所幫助。
