Pandas數(shù)據(jù)類型自行變換及數(shù)據(jù)類型轉(zhuǎn)換失敗問題分析與解決
Pandas數(shù)據(jù)類型自行變換及數(shù)據(jù)類型轉(zhuǎn)換失敗
最近,在進(jìn)行數(shù)據(jù)處理過程中,頻繁使用Pandas進(jìn)行DataFrame關(guān)聯(lián)、合并、數(shù)據(jù)類型變換操作,當(dāng)?shù)阶詈髷?shù)據(jù)入庫(MongoDB)時(shí),出現(xiàn)部分整型數(shù)據(jù)變成浮點(diǎn)型,以及時(shí)間轉(zhuǎn)字符串存儲時(shí),偶爾出現(xiàn)少部分存儲為時(shí)間戳整型數(shù)據(jù)(也就是說偶爾出現(xiàn)時(shí)間轉(zhuǎn)換為字符串轉(zhuǎn)換失敗的情況),
如下圖所示。
1. 整型變浮點(diǎn)型情況
1.1. 問題情況再現(xiàn)
1.1.1. 空值情況
在DataFrame表間關(guān)聯(lián)(merge)、合并(concat)過程中,容易出現(xiàn)數(shù)據(jù)為空的情況,則其對應(yīng)的數(shù)據(jù)列將為float64。
import pandas as pd df1 = pd.DataFrame({'yearmonth': ['202201','202202','202203'], 'monthnum': [1,2,3]}) df2 = pd.DataFrame({'yearmonth': ['202201','202202'], 'testint': [11,12]}) print('df2數(shù)據(jù)類型\n',df2.dtypes) df = pd.merge(left=df1,right=df2,how='left',on=['yearmonth']) print('連接合并后數(shù)據(jù)類型\n',df.dtypes) df
運(yùn)行程序輸出結(jié)果如下所示,“testint”列的數(shù)據(jù)類型由int64變成float64。
1.1.2. 正負(fù)無窮情況(除數(shù)為0)
在DataFrame表中,進(jìn)行數(shù)據(jù)計(jì)算過程中,如果出現(xiàn)除數(shù)為零,則表示為正負(fù)無窮,對應(yīng)的列為float64類型。
import pandas as pd df1 = pd.DataFrame({'yearmonth': ['202201','202202','202203'], 'monthnum': [1,2,3]}) print('df1數(shù)據(jù)類型\n',df1.dtypes) df1.loc[:,'monthnum'] = df1['monthnum']/0 print('除零后,df1數(shù)據(jù)類型\n',df1.dtypes) df1
1.1.3. 讀取含有空值的數(shù)據(jù)源
以讀取簡單的csv數(shù)據(jù)文件為例:
import pandas as pd df = pd.read_csv('nan.csv') print('數(shù)據(jù)類型\n',df.dtypes) df
數(shù)據(jù)表nan.csv中,B列有個(gè)空值,則讀取數(shù)據(jù)后,B列為float64類型。
1.2. 小結(jié)
對于DataFrame表,在數(shù)據(jù)處理過程中,如果出現(xiàn)空值(nan)、正負(fù)無窮(inf),pandas將轉(zhuǎn)換為默認(rèn)的float64數(shù)據(jù)類型。
1.3. 解決方案
在關(guān)鍵點(diǎn),例如存儲、計(jì)算前,如有必要,按數(shù)據(jù)字典定義類型,強(qiáng)制統(tǒng)一轉(zhuǎn)換為定義類型。
注意:
- 首先,把空值處理掉,例如填充0,或其他需要的值;
- 如果,一列存在多種類型數(shù)據(jù),需要單獨(dú)處理,詳見后續(xù)介紹。
2. 時(shí)間類型轉(zhuǎn)字符串失敗情況
2.1. 關(guān)于pandas時(shí)間類型與整型、字符串型轉(zhuǎn)換
序號 | 功能 | 原數(shù)據(jù)類型 | 目標(biāo)數(shù)據(jù)類型 | 方法 |
---|---|---|---|---|
1 | 時(shí)間轉(zhuǎn)整型 | datetime[ns] | int64 | df[‘列名’].astype(‘int64’) |
2 | 時(shí)間轉(zhuǎn)字符串 | datetime[ns] | str(object) | df[‘列名’].dt.strftime(‘%Y-%m-%d’) |
3 | 整型轉(zhuǎn)時(shí)間 | int64 | datetime[ns] | df[‘列名’].astype(‘datetime64[ns]’) |
4 | 字符串轉(zhuǎn)時(shí)間 | str(object) | datetime[ns] | df[‘列名’]…astype(‘datetime64’) |
其中:時(shí)間類型單個(gè)數(shù)據(jù)的類型為
<class 'pandas._libs.tslibs.timestamps.Timestamp'>
對象,其他為正常python數(shù)據(jù)類型,例如int、str等。
import pandas as pd import time df = pd.DataFrame({'yearmonth': ['202201','202202','202202'], 'monthnum': [1,2,1], 'datetime': [pd.Timestamp('2018-03-10 21:00:01'),pd.Timestamp('2019-03-10 12:02:00'),pd.Timestamp('2019-09-10 12:02:00')]}) df['datetimenum'] = df['datetime'].astype('int64') df
df.loc[:,'datetimenum'] = df['datetimenum'].astype('datetime64[ns]') df['datetimestr'] = df['datetime'].dt.strftime('%Y-%m-%d') df.loc[:,'datetimestr'] = df['datetimestr'].astype('datetime64')
2.2. 單列復(fù)雜數(shù)據(jù)類型情況及解決方法
由于很難模擬出時(shí)間類型轉(zhuǎn)字符串失敗情況,文中僅僅采用按行強(qiáng)制賦值方式構(gòu)建分析樣本。
分別直接賦值整型時(shí)間戳和字符串時(shí)間,如下列所示。
df.loc[1,'datetimenum'] = 1611532800000 df.loc[2,'datetimestr'] = '2022-08-10' df.dtypes # 下面代碼報(bào)錯(cuò)! df.loc[:,'datetimenum'] = df['datetimenum'].astype('datetime64') df.loc[:,'datetimenum'] = df['datetimenum'].astype('datetime64[ns]')
對于目標(biāo)為時(shí)間類型的列(本例中的datetimenum),如果某行存儲一個(gè)整型數(shù)據(jù),即使是時(shí)間戳整數(shù),這種混合情況,表現(xiàn)類型為“Object”,在類型轉(zhuǎn)換時(shí)將會報(bào)錯(cuò)。
ValueError: mixed datetimes and integers in passed array
對于這種復(fù)雜混合類型的列,可以采用逐行按具體數(shù)據(jù)類型轉(zhuǎn)換到目標(biāo)類型,如下文把混合時(shí)間、字符串、時(shí)間戳整數(shù)的數(shù)據(jù)統(tǒng)一轉(zhuǎn)換為字符串類型。
import numpy as np import time def f(timeNum): if type(timeNum) == type(1): timeTemp = float(timeNum/1000) tupTime = time.localtime(timeTemp) #stadardTime = time.strftime("%Y-%m-%d %H:%M:%S", tupTime) stadardTime = time.strftime("%Y-%m-%d", tupTime) elif type(timeNum) == type('2022-08-18'): stadardTime = timeNum else: print(type(timeNum)) #stadardTime = timeNum.strftime("%Y-%m-%d %H:%M:%S") stadardTime = timeNum.strftime("%Y-%m-%d") print(timeNum) return pd.Series([stadardTime]) df['datetimestr'] = df['datetimestr'].apply(lambda x:f(x)) df
2.3. 相關(guān)內(nèi)容,數(shù)據(jù)類型識別
Python中常用isinstance()和type()內(nèi)置函數(shù)判斷數(shù)據(jù)類型:
isinstance()
是Python中的一個(gè)內(nèi)建函數(shù)。是用來判斷一個(gè)對象的變量類型。
isinstance(object, classinfo)
- 如果參數(shù)object是classinfo的實(shí)例,或者object是classinfo類的子類的一個(gè)實(shí)例, 返回True。
- 如果object不是一個(gè)給定類型的的對象, 則返回結(jié)果總是False。
type
函數(shù)是Python的內(nèi)置函數(shù),返回參數(shù)的類型。
# type函數(shù) variateint = 100 variatestr = '100' if type(variateint) == type(1): print('int') if type(variatestr) == type('hello'): print('str') # isinstance函數(shù) if isinstance(variateint,int): print('int') if isinstance(variatestr,str): print('str')
補(bǔ)充:
type只接收一個(gè)參數(shù),不但可以判斷變量是否屬于某個(gè)類型,而且可以得到參數(shù)變量未知的所屬的類型;
而isinstance只能判斷是否屬于某個(gè)已知類型,不能直接得到變量未知的所屬的類型
總結(jié)
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
python-docx修改已存在的Word文檔的表格的字體格式方法
今天小編就為大家分享一篇python-docx修改已存在的Word文檔的表格的字體格式方法,具有很好的參考價(jià)值,希望對大家有所幫助。一起跟隨小編過來看看吧2018-05-05Python機(jī)器學(xué)習(xí)NLP自然語言處理基本操作精確分詞
本文是Python機(jī)器學(xué)習(xí)NLP自然語言處理系列文章,帶大家開啟一段學(xué)習(xí)自然語言處理 (NLP) 的旅程. 本文主要學(xué)習(xí)NLP自然語言處理基本操作之如何精確分詞2021-09-09Python pathlib模塊使用方法及實(shí)例解析
這篇文章主要介紹了Python pathlib模塊使用方法及實(shí)例解析,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-10-10python實(shí)現(xiàn)網(wǎng)站的模擬登錄
這篇文章主要介紹了python實(shí)現(xiàn)網(wǎng)站的模擬登錄的相關(guān)資料,通過自己構(gòu)造post數(shù)據(jù)來用Python實(shí)現(xiàn)登錄過程,需要的朋友可以參考下2016-01-01python+pygame實(shí)現(xiàn)代碼雨(黑客帝國既視感)
這篇文章主要介紹了python+pygame實(shí)現(xiàn)代碼雨(黑客帝國既視感),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2021-03-03PyTorch中tensor.backward()函數(shù)的詳細(xì)介紹及功能實(shí)現(xiàn)
backward()?函數(shù)是PyTorch框架中自動求梯度功能的一部分,它負(fù)責(zé)執(zhí)行反向傳播算法以計(jì)算模型參數(shù)的梯度,這篇文章主要介紹了PyTorch中tensor.backward()函數(shù)的詳細(xì)介紹,需要的朋友可以參考下2024-02-02在Django框架中運(yùn)行Python應(yīng)用全攻略
這篇文章主要介紹了在Django框架中運(yùn)行Python應(yīng)用全攻略,在這之前必須搭建好簡單的視圖和模版,接下來便是本文中所述的核心內(nèi)容應(yīng)用配置,需要的朋友可以參考下2015-07-07