当pandas遇上数据类型问题
原文: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
为什么这么在意数据类型?
一般情况我们都不会去想数据类型问题,直到发现问题出现了。
import pandas as pd
import numpy as np
df = pd.read_csv('sales_data_types.csv')
df
一打眼看这结果,我就发现一个问题。Customer number 应该是整数,不应该带有小数点(浮点型数字)。2016和2017是字符串,但是如果后续对2016和2017列进行数值计算,肯定不行,所以也应该转换成数字型数据。看来问题还是有不少对,那么我们看看所有字段的数据类型
df.dtypes
Customer Number float64
Customer Name object
2016 object
2017 object
Percent Growth object
Jan Units object
Month int64
Day int64
Year int64
Active object
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 转为整数型数据。
df['Customer Number'].astype('int')
0 10002
1 552278
2 23477
3 24900
4 651029
Name: Customer Number, dtype: int64
为了将原始数据更改,我们需要进行原地操作,将处理结果更新到原始数据中来
df['Customer Number'] = df['Customer Number'].astype('int')
df.dtypes
Customer Number int64
Customer Name object
2016 object
2017 object
Percent Growth object
Jan Units object
Month int64
Day int64
Year int64
Active object
dtype: object
现在我们再看看心的dataframe
df
我们试着将 2016、2017、PercentGrowth、JanUnits列
从 字符串 转化为 数字
df['2016'].astype('int')
ValueError Traceback (most recent call last)
同样的问题出现在2017、Percent Growth、Jan Units列, 说明astype这种方法不是万能的,还是需要设计自定义转换函数,具体问题具体处理。
二、自定义转换函数
这里我们以 2016和2017列为例,在强制从字符串转为数字之前,我们需要先将 "$"、"."、","
剔除掉,然后再转换。
def convert_currency(val):
"""
将字符串val转为一个浮点型数值
- 移除 $
- 去掉 ','、 '.'
- 转为 浮点型数值
"""
new_val = val.replace(',', '').replace('$', '')
return float(new_val)
df['2016'] = df['2016'].apply(convert_currency)
df['2017'] = df['2017'].apply(convert_currency)
df
可能有的人会说用 lambda 一行代码就能解决的事儿
#df['2016'] = df['2016'].apply(lambda x:x.replace('.', '').replace(',', '')).astype('float')
上面这一样确实能一行搞定,但是我不推荐,原因有:
对于初学者不友好,你写的能看懂,但不代表其他人能看懂你的代码
如果要处理的字段比较多,我们可以多次调用自定义函数。比如定义好以后,在2016和2017上调用
下面我们再用自定义方法处理 PercentGrowth
列
def convert_percent(val):
"""
将百分比字符串数据 转为 浮点型数值
- 移除 '%'
- 除以100
"""
new_val = val.replace('%', '')
return float(new_val)/100
df['Percent Growth'] = df['Percent Growth'].apply(convert_percent)
df['Percent Growth']
0 0.30
1 0.10
2 0.25
3 0.04
4 -0.15
Name: Percent Growth, dtype: float64
如果你还是想用lambda处理 PercentGrowth
, 那么处理方法如下
#df['Percent Growth'] = df['Percent Growth'].apply(lambda x: x.replace('%', '')).astype('float')/100
最后我们要将 Active
从 Y、X
转为 True和False
。
def convert_active(val):
if val=='Y':
return True
else:
return False
df['Active'] = df['Active'].apply(convert_active)
df['Active']
0 True
1 True
2 True
3 True
4 False
Name: Active, dtype: bool
这里我们不自定义函数,也可以用numpy中的np.where函数
np.where(condition, do1, do2)
如果condition满足条件,执行do1,否则执行do2
#df['Active'] = np.where(df['Active']=='Y', True, False)
#df['Active']
三、pandas内置的处理函数
pandas还有 pd.to_numeric(arg,errors='raise')和pd.to_datetime(arg,errors='raise')
函数帮助我们转为数据类型。
errors参数有:
raise, errors默认为raise
ignore 忽略错误
coerce 将错误数据标注为NaN
pd.to_numeric(df['Jan Units'], errors='coerce')
0 500.0
1 700.0
2 125.0
3 75.0
4 NaN
Name: Jan Units, dtype: float64
我们将处理结果中的NaN用0替代
df['Jan Units'] = pd.to_numeric(df['Jan Units'], errors='coerce').fillna(0)
df['Jan Units']
0 500.0
1 700.0
2 125.0
3 75.0
4 0.0
Name: Jan Units, dtype: float64
最后一个要转换的是日期数据,我们要把 Year、Month、Day
三列数据 转化 为一个日期数据型新列
df['Start_Date'] = pd.to_datetime(df[['Month', 'Day', 'Year']])
df
四、导入数据时转换数据类型
除了上面的三种方法,实际上我们也可以在导入数据的时候就处理好。
df2 = pd.read_csv("sales_data_types.csv",
dtype = {'Customer Number': 'int'},
converters={'2016': convert_currency,
'2017': convert_currency,
'Percent Growth': convert_percent,
'Jan Units': lambda x: pd.to_numeric(x, errors='coerce'),
'Active': lambda x: True if x=='Y' else False})
df2
df2.dtypes
Customer Number int64
Customer Name object
2016 float64
2017 float64
Percent Growth float64
Jan Units float64
Month int64
Day int64
Year int64
Active bool
dtype: object
总结
做数据分析时,我们要确保数据类型是正常的,这要求我们导入数据后就要检查数据类型。
如果数据类型不满足我们的需求,需要转换数据类型,思路有
使用astype()方法强制转化dtype
自定义一个数据转换函数函数
使用pandas内置的tonumeric()和todatetime()
导入数据时转换数据类型
推荐文章
顺利开班 | python爬虫分析2019年杭州国庆工作坊顺利开班
课件获取方式,请在公众号后台回复关键词“pandas真香”,
其实我想用“大邓真帅” 这个关键词😄,你们还能想到哪些关键词,欢迎留言~