查看原文
其他

当pandas遇上数据类型问题

大邓 大邓和他的Python 2022-07-09


原文:Overview of Pandas Data Types作者:Chris Moffitt链接: https://pbpython.com/pandas_dtypes.html译者: 大邓

当我们做数据分析时,确保自己使用的是正确的数据类型,这一点很重要。而在pandas中,一般情况下会根据我们导入的数据,自动分配最合适的数据类型。

但是有时候pandas也会犯错,这时候我们就需要diy自定义数据类型。本文主要将pandas的dtype,如何进行数据类型的操作。

pands数据类型

数据类型是编程语言的基础性概念,ta会告诉电脑如何存储数据、如何操作数据。

例如,当我们给程序两个数字,进行 5+10操作时, 程序要能理解这是两个整数,且知道整数是可以进行加法操作。

而当有两个字符串,进行 "cat"+"hat" 我们知道会得到 cathat

现在可能大家有点疑惑,python、pandas、numpy代表着数据分析领域三大数据类型门派,彼此会有重合,导致各位看官学杂学邪,走火入魔。我列一个表格,以作区分。

本文主要学习pandas的:

  • object

  • int64

  • float64

  • datetime64

  • bool

为什么这么在意数据类型?

一般情况我们都不会去想数据类型问题,直到发现问题出现了。

  1. import pandas as pd

  2. import numpy as np


  3. df = pd.read_csv('sales_data_types.csv')

  4. df

一打眼看这结果,我就发现一个问题。Customer number 应该是整数,不应该带有小数点(浮点型数字)。2016和2017是字符串,但是如果后续对2016和2017列进行数值计算,肯定不行,所以也应该转换成数字型数据。看来问题还是有不少对,那么我们看看所有字段的数据类型

  1. df.dtypes

  1. Customer Number float64

  2. Customer Name object

  3. 2016 object

  4. 2017 object

  5. Percent Growth object

  6. Jan Units object

  7. Month int64

  8. Day int64

  9. Year int64

  10. Active object

  11. dtype: object

数据中暴露的问题

现在我们可以总结下这个数据有哪些问题:

  • Customer number 应该是int64,不应该是float64

  • 2016和2017两个字段是object字符串,但我们应该将其转换为float64或者int64

  • Percent Growth 应该是数字,但是这里是object字符串

  • Year、Month、Day 三个字段应该合并为一个datetime类型的日期数据

  • Active应该是bool型数据

转换数据类型的思路

  • 使用astype()方法强制转化dtype

  • 自定义一个数据转换函数函数

  • 使用pandas内置的tonumeric()和todatetime()

  • 导入数据时转换数据类型

一、使用astype()方法

处理pandas数据类型最简单的办法是astype(),例如,我们将Customer Number 转为整数型数据。

  1. df['Customer Number'].astype('int')

  1. 0 10002

  2. 1 552278

  3. 2 23477

  4. 3 24900

  5. 4 651029

  6. Name: Customer Number, dtype: int64

为了将原始数据更改,我们需要进行原地操作,将处理结果更新到原始数据中来

  1. df['Customer Number'] = df['Customer Number'].astype('int')

  2. df.dtypes

  1. Customer Number int64

  2. Customer Name object

  3. 2016 object

  4. 2017 object

  5. Percent Growth object

  6. Jan Units object

  7. Month int64

  8. Day int64

  9. Year int64

  10. Active object

  11. dtype: object

现在我们再看看心的dataframe

  1. df

我们试着将 20162017PercentGrowthJanUnits 从 字符串 转化为 数字

  1. df['2016'].astype('int')


ValueError Traceback (most recent call last)in----> 1 df['2016'].astype('int') ... ValueError: invalid literal for int() with base 10: '$125,000.00'

同样的问题出现在2017、Percent Growth、Jan Units列, 说明astype这种方法不是万能的,还是需要设计自定义转换函数,具体问题具体处理。

二、自定义转换函数

这里我们以 2016和2017列为例,在强制从字符串转为数字之前,我们需要先将 "$"".""," 剔除掉,然后再转换。

  1. def convert_currency(val):

  2. """

  3. 将字符串val转为一个浮点型数值

  4. - 移除 $

  5. - 去掉 ','、 '.'

  6. - 转为 浮点型数值

  7. """

  8. new_val = val.replace(',', '').replace('$', '')

  9. return float(new_val)

  1. df['2016'] = df['2016'].apply(convert_currency)

  2. df['2017'] = df['2017'].apply(convert_currency)

  3. df

可能有的人会说用 lambda 一行代码就能解决的事儿

  1. #df['2016'] = df['2016'].apply(lambda x:x.replace('.', '').replace(',', '')).astype('float')

上面这一样确实能一行搞定,但是我不推荐,原因有:

  • 对于初学者不友好,你写的能看懂,但不代表其他人能看懂你的代码

  • 如果要处理的字段比较多,我们可以多次调用自定义函数。比如定义好以后,在2016和2017上调用

下面我们再用自定义方法处理 PercentGrowth

  1. def convert_percent(val):

  2. """

  3. 将百分比字符串数据 转为 浮点型数值

  4. - 移除 '%'

  5. - 除以100

  6. """


  7. new_val = val.replace('%', '')

  8. return float(new_val)/100


  9. df['Percent Growth'] = df['Percent Growth'].apply(convert_percent)

  10. df['Percent Growth']

  1. 0 0.30

  2. 1 0.10

  3. 2 0.25

  4. 3 0.04

  5. 4 -0.15

  6. Name: Percent Growth, dtype: float64

如果你还是想用lambda处理 PercentGrowth, 那么处理方法如下

  1. #df['Percent Growth'] = df['Percent Growth'].apply(lambda x: x.replace('%', '')).astype('float')/100

最后我们要将 ActiveYX 转为 TrueFalse

  1. def convert_active(val):

  2. if val=='Y':

  3. return True

  4. else:

  5. return False


  6. df['Active'] = df['Active'].apply(convert_active)

  7. df['Active']

  1. 0 True

  2. 1 True

  3. 2 True

  4. 3 True

  5. 4 False

  6. Name: Active, dtype: bool

这里我们不自定义函数,也可以用numpy中的np.where函数

np.where(condition, do1, do2)

如果condition满足条件,执行do1,否则执行do2

  1. #df['Active'] = np.where(df['Active']=='Y', True, False)

  2. #df['Active']

三、pandas内置的处理函数

pandas还有 pd.to_numeric(arg,errors='raise')和pd.to_datetime(arg,errors='raise') 函数帮助我们转为数据类型。

errors参数有:

  • raise, errors默认为raise

  • ignore 忽略错误

  • coerce 将错误数据标注为NaN

  1. pd.to_numeric(df['Jan Units'], errors='coerce')

  1. 0 500.0

  2. 1 700.0

  3. 2 125.0

  4. 3 75.0

  5. 4 NaN

  6. Name: Jan Units, dtype: float64

我们将处理结果中的NaN用0替代

  1. df['Jan Units'] = pd.to_numeric(df['Jan Units'], errors='coerce').fillna(0)

  2. df['Jan Units']

  1. 0 500.0

  2. 1 700.0

  3. 2 125.0

  4. 3 75.0

  5. 4 0.0

  6. Name: Jan Units, dtype: float64

最后一个要转换的是日期数据,我们要把 YearMonthDay 三列数据 转化 为一个日期数据型新列

  1. df['Start_Date'] = pd.to_datetime(df[['Month', 'Day', 'Year']])

  2. df

四、导入数据时转换数据类型

除了上面的三种方法,实际上我们也可以在导入数据的时候就处理好。

  1. df2 = pd.read_csv("sales_data_types.csv",

  2. dtype = {'Customer Number': 'int'},

  3. converters={'2016': convert_currency,

  4. '2017': convert_currency,

  5. 'Percent Growth': convert_percent,

  6. 'Jan Units': lambda x: pd.to_numeric(x, errors='coerce'),

  7. 'Active': lambda x: True if x=='Y' else False})


  8. df2

  1. df2.dtypes

  1. Customer Number int64

  2. Customer Name object

  3. 2016 float64

  4. 2017 float64

  5. Percent Growth float64

  6. Jan Units float64

  7. Month int64

  8. Day int64

  9. Year int64

  10. Active bool

  11. dtype: object

总结

做数据分析时,我们要确保数据类型是正常的,这要求我们导入数据后就要检查数据类型。

如果数据类型不满足我们的需求,需要转换数据类型,思路有

  • 使用astype()方法强制转化dtype

  • 自定义一个数据转换函数函数

  • 使用pandas内置的tonumeric()和todatetime()

  • 导入数据时转换数据类型


推荐文章

python爬虫与文本数据分析 系列课

pip安装问题解决办法

tabulate:好看的字符串表格库

如何理解pandas中的transform函数

计算社会经济学

免费视频课《Python快速入门》

初学Python常见异常错误

Python 函数式编程指北,不只是面向对象哦

一行pandas代码生成哑变量

顺利开班 | python爬虫分析2019年杭州国庆工作坊顺利开班

圆满落幕 | Python 爬虫分析杭州国庆工作坊圆满落幕

文本数据分析文章汇总(2016-至今)



课件获取方式,请在公众号后台回复关键词“pandas真香”,


其实我想用“大邓真帅” 这个关键词😄,你们还能想到哪些关键词,欢迎留言~


您可能也对以下帖子感兴趣

文章有问题?点此查看未经处理的缓存