Pandas数据类型自行变换及数据类型转换失败问题分析与解决

 更新时间:2023年06月21日 15:01:51   作者:肖永威  
这篇文章主要介绍了Pandas数据类型自行变换及数据类型转换失败问题分析与解决方案,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教

Pandas数据类型自行变换及数据类型转换失败

最近,在进行数据处理过程中,频繁使用Pandas进行DataFrame关联、合并、数据类型变换操作,当到最后数据入库(MongoDB)时,出现部分整型数据变成浮点型,以及时间转字符串存储时,偶尔出现少部分存储为时间戳整型数据(也就是说偶尔出现时间转换为字符串转换失败的情况),

如下图所示。

1. 整型变浮点型情况

1.1. 问题情况再现

1.1.1. 空值情况

在DataFrame表间关联(merge)、合并(concat)过程中,容易出现数据为空的情况,则其对应的数据列将为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数据类型\n',df2.dtypes)
df = pd.merge(left=df1,right=df2,how='left',on=['yearmonth'])
print('连接合并后数据类型\n',df.dtypes)
df

运行程序输出结果如下所示,“testint”列的数据类型由int64变成float64。

1.1.2. 正负无穷情况(除数为0)

在DataFrame表中,进行数据计算过程中,如果出现除数为零,则表示为正负无穷,对应的列为float64类型。

import pandas as pd
df1 = pd.DataFrame({'yearmonth': ['202201','202202','202203'],
                   'monthnum': [1,2,3]})
print('df1数据类型\n',df1.dtypes)
df1.loc[:,'monthnum'] = df1['monthnum']/0
print('除零后,df1数据类型\n',df1.dtypes)
df1

1.1.3. 读取含有空值的数据源

以读取简单的csv数据文件为例:

import pandas as pd
df = pd.read_csv('nan.csv')
print('数据类型\n',df.dtypes)
df

数据表nan.csv中,B列有个空值,则读取数据后,B列为float64类型。

1.2. 小结

对于DataFrame表,在数据处理过程中,如果出现空值(nan)、正负无穷(inf),pandas将转换为默认的float64数据类型。

1.3. 解决方案

在关键点,例如存储、计算前,如有必要,按数据字典定义类型,强制统一转换为定义类型。

注意:

  • 首先,把空值处理掉,例如填充0,或其他需要的值;
  • 如果,一列存在多种类型数据,需要单独处理,详见后续介绍。

2. 时间类型转字符串失败情况

2.1. 关于pandas时间类型与整型、字符串型转换

序号功能原数据类型目标数据类型方法
1时间转整型datetime[ns]int64df[‘列名’].astype(‘int64’)
2时间转字符串datetime[ns]str(object)df[‘列名’].dt.strftime(‘%Y-%m-%d’)
3整型转时间int64datetime[ns]df[‘列名’].astype(‘datetime64[ns]’)
4字符串转时间str(object)datetime[ns]df[‘列名’]…astype(‘datetime64’)

其中:时间类型单个数据的类型为

<class 'pandas._libs.tslibs.timestamps.Timestamp'>

对象,其他为正常python数据类型,例如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. 单列复杂数据类型情况及解决方法

由于很难模拟出时间类型转字符串失败情况,文中仅仅采用按行强制赋值方式构建分析样本。

分别直接赋值整型时间戳和字符串时间,如下列所示。

df.loc[1,'datetimenum'] = 1611532800000
df.loc[2,'datetimestr'] = '2022-08-10'
df.dtypes
# 下面代码报错!
df.loc[:,'datetimenum'] = df['datetimenum'].astype('datetime64')
df.loc[:,'datetimenum'] = df['datetimenum'].astype('datetime64[ns]')

对于目标为时间类型的列(本例中的datetimenum),如果某行存储一个整型数据,即使是时间戳整数,这种混合情况,表现类型为“Object”,在类型转换时将会报错。

ValueError: mixed datetimes and integers in passed array

对于这种复杂混合类型的列,可以采用逐行按具体数据类型转换到目标类型,如下文把混合时间、字符串、时间戳整数的数据统一转换为字符串类型。

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. 相关内容,数据类型识别

Python中常用isinstance()和type()内置函数判断数据类型:

isinstance()是Python中的一个内建函数。是用来判断一个对象的变量类型。

isinstance(object, classinfo)
  • 如果参数object是classinfo的实例,或者object是classinfo类的子类的一个实例, 返回True。
  • 如果object不是一个给定类型的的对象, 则返回结果总是False。

type函数是Python的内置函数,返回参数的类型。

# type函数
variateint = 100
variatestr = '100'
if type(variateint) == type(1):
    print('int')
if type(variatestr) == type('hello'):
    print('str')
# isinstance函数
if isinstance(variateint,int):
    print('int')
if isinstance(variatestr,str):
    print('str')

补充:

type只接收一个参数,不但可以判断变量是否属于某个类型,而且可以得到参数变量未知的所属的类型;

而isinstance只能判断是否属于某个已知类型,不能直接得到变量未知的所属的类型

总结

以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。

相关文章

  • 利用python打印出菱形、三角形以及矩形的方法实例

    利用python打印出菱形、三角形以及矩形的方法实例

    最近在开发中遇到一个问题,需要利用python实现菱形、三角形以及矩形等形状,发现网上这方面的资料较少,所以总结分享下,这篇文章主要给大家介绍了关于利用python打印出菱形、三角形以及矩形的相关资料,需要的朋友可以参考借鉴,下面来一起看看吧。
    2017-08-08
  • Python 二叉树的层序建立与三种遍历实现详解

    Python 二叉树的层序建立与三种遍历实现详解

    这篇文章主要介绍了Python 二叉树的层序建立与三种遍历实现详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2019-07-07
  • 使用IPython或Spyder将省略号表示的内容完整输出

    使用IPython或Spyder将省略号表示的内容完整输出

    这篇文章主要介绍了使用IPython或Spyder将省略号表示的内容完整输出,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2020-04-04
  • wxPython电子表格功能wx.grid实例教程

    wxPython电子表格功能wx.grid实例教程

    这篇文章主要介绍了wxPython电子表格功能wx.grid实例教程,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2019-11-11
  • 详细探究Python中的字典容器

    详细探究Python中的字典容器

    这篇文章主要介绍了Python中的字典容器,本文来自于IBM官方网站技术文档,需要的朋友可以参考下
    2015-04-04
  • 解决df.to_csv()中文件名的问题

    解决df.to_csv()中文件名的问题

    这篇文章主要介绍了解决df.to_csv()中文件名的问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2023-08-08
  • Numpy维度知识总结

    Numpy维度知识总结

    这篇文章主要介绍了Numpy维度知识总结,因为在numpy里一维既可以做行向量也可以做列向量,那对于任意一个给定的一维向量,我们就无法确定他到底是行向量还是列向量,为了防止这种尴尬的境地,习惯上用二维矩阵而不是一维矩阵来表示行向量和列向量,需要的朋友可以参考下
    2023-09-09
  • python 提取tuple类型值中json格式的key值方法

    python 提取tuple类型值中json格式的key值方法

    今天小编就为大家分享一篇python 提取tuple类型值中json格式的key值方法,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2018-12-12
  • python OpenCV学习笔记之绘制直方图的方法

    python OpenCV学习笔记之绘制直方图的方法

    本篇文章主要介绍了python OpenCV学习笔记之绘制直方图的方法,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2018-02-02
  • anaconda的安装和配置环境及导入pycharm的方法

    anaconda的安装和配置环境及导入pycharm的方法

    这篇文章主要介绍了anaconda的安装和配置环境及导入pycharm的方法,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2021-03-03

最新评论