今天是 Kaggle 数据清洗挑战的第三天,任务是解析 date 型数据。相信我们都遇到过此类情况,拿到的数据集中有需要分析的日期数据,但它们的类型是 String,不便作图,也不适合作为一个 factor 帮助我们进行预测。也可能你拿到的是 Timestamp 类型的数据(如:2005-10-30 T 10:45 UTC),而你只需要年份和月份信息。遇到这些情况,我们都可以使用 python 对其进行解析~
具体分为 5 个部分:
- Get our environment set up
- Check the data type of our date column
- Convert our date columns to datetime
- Select just the day of the month from our column
- Plot the day of the month to check the date parsing
1、搭建环境
首先还是引入需要的 lib 包和数据集,今天的数据是关于地震信息的:
# modules we'll use
import pandas as pd
import numpy as np
import seaborn as sns
import datetime
# read in our data
landslides = pd.read_csv("../input/landslide-events/catalog.csv")
# set seed for reproducibility
np.random.seed(0)
2、查看日期数据的类型
我们先读取日期列的前几条数据,确保它真的含有日期数据:
# print the first few rows of the date column
print(earthquakes['Date'].head())
从结果看,这些数据确实包含日期信息,但机器并不知道它们代表着日期。我们看到下面的 dtype 是 object,Pandas 中用 object 保存各种类型的数据,但大多数都含有字符串。我们也可以不读取前几条数据,直接查看某一列数据的类型:
earthquakes['Date'].dtype
3、将日期数据的类型变为 datetime
现在我们知道,这些代表日期的数据并没有被机器识别为日期,所以就需要手动将它们转换为 datetime 类型。这一步叫做 parsing date,因为我们要读取一段字符串,对它的组成部分进行解析。
我们可以借助 pandas 来解析这些日期数据,关于具体可能包含哪些部分,感兴趣的可以查看 Python's strftime directives。通过这步,我们能够解析出数据的各个部分,以及分隔它们的符号。例如:
* 1/17/07 has the format "%m/%d/%y"
* 17-1-2007 has the format "%d-%m-%Y"
通过上一步,我们得知该地震信息数据集中的日期数据组成为 "month/day/four-digit year",所以我们可以按这个格式来解析所有的日期数据:
# create a new column, date_parsed, with the parsed dates
earthquakes['date_parsed'] = pd.to_datetime(earthquakes['Date'], format = "%m/%d/%Y", errors='coerce')
⚠️注意:由于数据中还有个别不是 "month/day/four-digit year" 格式,直接转换的话会报错,Pandas 提供了一个可选的参数 errors,传入 errors='coerce',当遇到不能转换的数据就会将其置为 NaN,我们之后再对其进行特别处理~ 但如果我们不设定 format,这个错误就会被忽略,不过就无法得到特定格式的日期数据了,可能影响之后分析工作。
查看一下成功转换类型的数据:
earthquakes['date_parsed'].sample(5)
然后再处理之前的漏网之鱼,由于它们已经被置为 NaN,我们直接就可以查看了:
earthquakes['date_parsed'].loc[earthquakes['date_parsed'].isnull()]
我们看到有上面三条数据的格式需要特别处理,具体看一下它们到底什么样:
earthquakes['Date'].loc[[3378,7512,20650]]
然后我们可以手动对其进行处理:
earthquakes['date_parsed'][3378] = '1975-02-23'
earthquakes['date_parsed'][7512] = '1985-04-28'
earthquakes['date_parsed'][20650] = '2011-03-13'
至此日期数据的类型和格式就基本上完美了!
4、按 month 选取所有 day
为了检查我们刚才 parsing date 的成果,我们先从原始数据集中按 month 选取 day:
day_of_month_earthquakes = earthquakes['Date'].dt.day
这时候得到一个错误:
出现这个错误的原因是 dt.day() 方法不知道如何处理一个 object 类型的数据。再换成处理后的数据看看:
day_of_month_earthquakes = earthquakes['date_parsed'].dt.day
不报错了。
5、作图来再次检查 date parsing 效果
parsing date 过程中最怕出现的 bug 是搞混“月“和”日“,所以我们通过作图的方式来 double check 一下。
# remove na's
day_of_month_earthquakes = day_of_month_earthquakes.dropna()
# plot the day of the month
sns.distplot(day_of_month_earthquakes, kde=False, bins=31)
我们看到每个 1~30 每个日期的分布很平均,31 日偏低是因为只有一半月份有 31 日,恰好 31 日的数目大约是其他日子的 1/2,double-check 后可以确定我们的 date parsing 是成功的。
这就是 5 Day Challenge 第三天的内容,完毕~
欢迎关注我的知乎专栏【数据池塘】,专注于分享机器学习、数据挖掘相关内容:https://zhuanlan.zhihu.com/datapool
⬇️ 扫描下方二维码关注公众号【数据池塘】 ⬇️
回复【算法】,获取最全面的机器学习算法网络图: