数据类型强制转换与错误处理:`pd.to_numeric`, `pd.to_datetime`

好的,各位观众老爷们,欢迎来到今天的《数据类型强制转换与错误处理奇遇记》!我是你们的老朋友,数据界的老司机,今天就带大家一起闯荡一下 pd.to_numericpd.to_datetime 这两个数据转换界的“变形金刚”。

开场白:数据类型,你搞清楚了吗?

在数据分析的世界里,数据类型就像人的性格,千奇百怪,各有所长。有憨厚的整数型(int),有精打细算的浮点型(float),还有能说会道的字符串型(str)。但有时候,数据就像个叛逆期的孩子,明明应该是个数字,非要伪装成字符串,让我们头疼不已。

举个栗子 🌰:

你从一个CSV文件中读取了一列数据,本以为是价格,结果打印出来一看,全是字符串!这就像你满怀期待地打开一个礼物盒,结果发现里面装的是袜子一样令人失望。

import pandas as pd

data = {'价格': ['100', '200', '300.5', '400.25']}
df = pd.DataFrame(data)
print(df['价格'].dtype) # 输出:object (在Pandas中,object 通常代表字符串)

这时候,我们就需要请出我们今天的两位主角:pd.to_numericpd.to_datetime,让他们来“拨乱反正”,把这些叛逆的数据类型转换成我们需要的样子。

第一幕:pd.to_numeric——数字变形记

pd.to_numeric,顾名思义,就是把数据转换成数值类型的。它就像一个魔法棒,能把字符串、甚至是混合类型的数据,变成整数或浮点数。

1. 基本用法:简单粗暴,一步到位

最简单的用法就是直接把要转换的 Series 或 DataFrame 列丢给它:

import pandas as pd

data = {'价格': ['100', '200', '300.5', '400.25']}
df = pd.DataFrame(data)

df['价格'] = pd.to_numeric(df['价格'])
print(df['价格'].dtype) # 输出:float64
print(df['价格'])

看,字符串变成了浮点数,是不是很神奇?

2. errors 参数:错误处理的艺术

但是,现实往往比理想更骨感。如果你的数据里混入了一些不能转换成数字的“捣蛋分子”,比如字母、符号等等,pd.to_numeric 就会毫不留情地报错。

data = {'价格': ['100', '200', '300.5', 'abc']}
df = pd.DataFrame(data)

# df['价格'] = pd.to_numeric(df['价格']) # 这行代码会报错!

这时候,errors 参数就派上用场了。它有三个选项:

  • 'raise' (默认值):遇到错误直接报错,毫不留情。
  • 'coerce':遇到错误,把不能转换的值变成 NaN(Not a Number),也就是缺失值。
  • 'ignore':遇到错误,忽略它,保持原来的数据类型不变。

让我们来试试 'coerce'

import pandas as pd

data = {'价格': ['100', '200', '300.5', 'abc']}
df = pd.DataFrame(data)

df['价格'] = pd.to_numeric(df['价格'], errors='coerce')
print(df['价格'].dtype) # 输出:float64
print(df['价格'])

看到没,'abc' 变成了 NaN

'ignore' 就像一个鸵鸟,把头埋在沙子里,眼不见为净:

import pandas as pd

data = {'价格': ['100', '200', '300.5', 'abc']}
df = pd.DataFrame(data)

df['价格'] = pd.to_numeric(df['价格'], errors='ignore')
print(df['价格'].dtype) # 输出:object
print(df['价格'])

'abc' 依然是 'abc',世界还是那个世界,只是我们选择了视而不见。

3. downcast 参数:节约内存,从我做起

downcast 参数可以帮助我们把数值类型转换成更小的类型,从而节省内存空间。它有四个选项:

  • 'integer':尝试把数据转换成最小的整数类型(int8, int16, int32, int64)。
  • 'signed':与 'integer' 类似,但只考虑有符号整数。
  • 'unsigned':与 'integer' 类似,但只考虑无符号整数。
  • 'float':尝试把数据转换成最小的浮点数类型(float32, float64)。

举个栗子:

import pandas as pd

data = {'数量': ['10', '20', '30', '40']}
df = pd.DataFrame(data)

df['数量'] = pd.to_numeric(df['数量'], downcast='integer')
print(df['数量'].dtype) # 输出:int8 (取决于数据范围)
print(df['数量'])

如果数据范围比较小,比如都在 -128 到 127 之间,那么就会被转换成 int8,大大节省了内存。

表格总结 pd.to_numeric

参数 作用
errors 指定错误处理方式:'raise' (默认), 'coerce', 'ignore'
downcast 指定数值类型转换成更小的类型,节省内存:'integer', 'signed', 'unsigned', 'float'

第二幕:pd.to_datetime——时间旅行者的指南

pd.to_datetime,顾名思义,就是把数据转换成日期时间类型的。它就像一个时间机器,能把各种各样的日期时间格式,变成统一的 datetime64 类型。

1. 基本用法:化腐朽为神奇

最简单的用法:

import pandas as pd

dates = ['2023-10-26', '2023/10/27', '10/28/2023']
dates_series = pd.Series(dates)

dates_series = pd.to_datetime(dates_series)
print(dates_series.dtype) # 输出:datetime64[ns]
print(dates_series)

看到了吗?不管是 'YYYY-MM-DD' 还是 'YYYY/MM/DD',甚至是 'MM/DD/YYYY'pd.to_datetime 都能识别出来,并转换成统一的格式。

2. format 参数:指定日期时间格式

但有时候,pd.to_datetime 也不是万能的。如果你的日期时间格式太奇葩,它可能就认不出来了。这时候,就需要 format 参数来帮忙了。

format 参数可以指定日期时间的格式,让 pd.to_datetime 知道该怎么解析。

举个栗子:

import pandas as pd

dates = ['26-10-2023', '27-10-2023', '28-10-2023'] # DD-MM-YYYY 格式
dates_series = pd.Series(dates)

dates_series = pd.to_datetime(dates_series, format='%d-%m-%Y')
print(dates_series)

'%d' 表示日,'%m' 表示月,'%Y' 表示年(四位数)。

常用的格式代码:

  • %Y: 年(四位数)
  • %y: 年(两位数)
  • %m: 月(01-12)
  • %d: 日(01-31)
  • %H: 时(00-23)
  • %M: 分(00-59)
  • %S: 秒(00-59)

3. errors 参数:错误处理,似曾相识

pd.to_datetime 也有 errors 参数,作用和 pd.to_numeric 类似:

  • 'raise' (默认值):遇到错误直接报错。
  • 'coerce':遇到错误,把不能转换的值变成 NaT(Not a Time),也就是时间类型的缺失值。
  • 'ignore':遇到错误,忽略它,保持原来的数据类型不变。
import pandas as pd

dates = ['2023-10-26', 'abc', '2023-10-28']
dates_series = pd.Series(dates)

dates_series = pd.to_datetime(dates_series, errors='coerce')
print(dates_series)

'abc' 变成了 NaT

4. originunit 参数:从数字到时间

有时候,日期时间不是以字符串的形式存在,而是以数字的形式存在,比如 Unix 时间戳。这时候,我们可以用 originunit 参数来把数字转换成日期时间。

origin 参数指定起始时间,unit 参数指定数字的单位。

举个栗子:

import pandas as pd

timestamps = [1698307200, 1698393600, 1698480000] # Unix 时间戳 (秒)
timestamps_series = pd.Series(timestamps)

dates_series = pd.to_datetime(timestamps_series, unit='s', origin='1970-01-01')
print(dates_series)

'1970-01-01' 是 Unix 时间戳的起始时间,'s' 表示单位是秒。

表格总结 pd.to_datetime

参数 作用
format 指定日期时间的格式,让 pd.to_datetime 知道该怎么解析
errors 指定错误处理方式:'raise' (默认), 'coerce', 'ignore'
origin 指定起始时间,用于把数字转换成日期时间
unit 指定数字的单位,用于把数字转换成日期时间,例如 's' (秒), 'ms' (毫秒), 'us' (微秒), 'ns' (纳秒)

第三幕:实战演练——数据清洗小技巧

光说不练假把式,让我们来一个实战演练,看看如何用 pd.to_numericpd.to_datetime 来清洗数据。

假设我们有一个包含销售数据的 DataFrame:

import pandas as pd

data = {'日期': ['2023-10-26', '2023/10/27', '10/28/2023', '2023-10-29'],
        '商品': ['A', 'B', 'C', 'D'],
        '价格': ['100', '200', '300.5', 'abc'],
        '数量': ['10', '20', '30', '40']}
df = pd.DataFrame(data)
print(df)
print(df.dtypes)

数据类型有点乱,我们需要做以下几步:

  1. '日期' 列转换成 datetime64 类型。
  2. '价格' 列转换成 float64 类型,遇到错误变成 NaN
  3. '数量' 列转换成 int32 类型。
  4. NaN 值填充为 0。

代码如下:

import pandas as pd
import numpy as np

data = {'日期': ['2023-10-26', '2023/10/27', '10/28/2023', '2023-10-29'],
        '商品': ['A', 'B', 'C', 'D'],
        '价格': ['100', '200', '300.5', 'abc'],
        '数量': ['10', '20', '30', '40']}
df = pd.DataFrame(data)

# 1. 转换日期
df['日期'] = pd.to_datetime(df['日期'])

# 2. 转换价格
df['价格'] = pd.to_numeric(df['价格'], errors='coerce')

# 3. 转换数量
df['数量'] = pd.to_numeric(df['数量'], downcast='integer')

# 4. 填充 NaN 值
df.fillna(0, inplace=True)

print(df)
print(df.dtypes)

看,数据是不是变得干净多了?

结语:数据类型转换,任重道远

数据类型转换是数据分析中必不可少的一步,pd.to_numericpd.to_datetime 是我们手中的利器。掌握了它们,就能轻松应对各种奇葩的数据类型,让数据分析工作事半功倍。

当然,数据类型转换不是一蹴而就的,需要我们不断学习、实践、总结。希望今天的分享能对大家有所帮助。

记住,数据分析的世界,永远充满惊喜和挑战!

最后的彩蛋:

大家可以思考一下,如果你的数据中包含了中文字符,比如 '一千''两百',如何转换成数字呢? 欢迎在评论区留言,分享你的想法! 让我们一起进步,共同成长! 🚀

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注