特征工程是数据科学领域中的一个重要环节,它涉及到根据特定需求对数据特征(列)进行塑造和转换。例如,如果有人告诉他以每根20元的价格购买了10根热狗,那么实际上想要的是10根热狗的总价,即200元。通过在心中计算总价,将给定的数据转换成了对更有用的形式,这就是特征工程的精髓——通过添加新特征使数据更有意义。
特征工程工具
在数据科学中,特征工程是一个领域,它创建新特征或更新给定数据集中的特征,以满足和团队的目的。这使得数据更具信息性和可读性。不能仅凭头脑来完成所有工作,因此会使用像Excel、SQL、Python、R等工具,当然,也可以使用纸和笔。
R语言入门
R是一种主要用于数据科学工作的编程语言。可以使用R从简单的加法运算到创建复杂的数据科学算法。如果是R的新手,不用担心,这里有一个基本的R概述。首先,需要一个集成开发环境(IDE)来使用它。RStudio是PC上的一个不错选择。但建议使用Kaggle网站的笔记本。为什么呢?因为Kaggle是一个拥有大量数据集、专用工作环境、教程、竞赛等的网站。
访问 并注册,创建个人资料,并添加必要的信息。对于本教程,只需要下载一个数据集(2019年前三个月的自行车数据):
直接链接或间接链接,并选择文件 Divvy_Trips_2019_Q1.zip
,然后解压它。将这个数据添加到Kaggle笔记本中。为此,从菜单中转到代码部分,点击新建笔记本。然后会在笔记本的右上角看到添加数据,然后上传下载的数据集。
之后,从代码下拉菜单中从Python切换到R。这个数据集来自一个组织活动的自行车公司,每个活动都有一些持续时间。需要了解为什么客户不成为订阅者。
理解数据
首先,将使用 read.csv(path)
读取CSV(逗号分隔值)文件。kaggle_path
是在Kaggle上上传数据集的路径。注意不要输入数据链接,添加自己的,如 kaggle_path <- "文件链接"
。
kaggle_path <- "../input/cycle-data/Divvy_Trips_2019_Q1.csv"
raw_data <- read.csv(kaggle_path)
# 查看数据
head(raw_data) 或者使用 str() 理解数据结构
str(raw_data)
# 或者使用 glimpse(raw_data),gimpse 来自 dplyr 包
# 它提供了一个漂亮的视图
glimpse(raw_data)
数据问题
仅仅通过查看数据,就可以知道 start_time
和 end_time
没有以日期的形式给出(表示为chr),但它们实际上是日期和时间。而且行程持续时间是整数类型的数据,但它显示为字符。
转换日期和时间
as.Date(column_name)
:这个函数允许将数据转换为日期,例如:“09-09-12”将被转换为日期:09-09-12。但chr和日期之间有什么区别呢?日期格式是R存储数据的一种方式,所以“09-09-12”对R来说不是一个日期,它们只是字符,但as.Date(c(“09-09-12”))
是R的日期格式。[注意:它从1970年1月1日开始计算日期。]
as.Date()
不适用于时间,它不会理解时间。例如as.Date(c(“09-09-12 00:10:29”))
只给出09-09-12并忽略00:10:29。
as.POSIXlt(column_name)
/ as.POSIXct(column_name)
:这两个函数帮助转换日期和时间,制作一个完整的时间戳。现在如果输入as.POSIXlt(“09-09-12 00:10:29”)
/ as.POSIXct(“09-09-12 00:10:29”)
,将得到09-09-12 00:10:29作为一个时间戳对象。注意这两个函数的区别在于一个以列表形式存储数据,另一个从1970年1月1日开始计数。
# 将 start_time 转换为日期-时间
raw_data$start_time <- as.POSIXlt(raw_data$start_time) # 用于开始时间
raw_data$end_time <- as.POSIXlt(raw_data$end_time) # 用于结束时间
print("as.POSIXlt()")
str(raw_data$start_time)
print("as.Date()")
str(tester) # as.data.frame 用于转换为数据框
输出
[1] "as.POSIXlt()"
POSIXlt[1:365069], 格式: "2019-01-01 00:04:37" "2019-01-01 00:08:13" "2019-01-01 00:13:23" ...
[1] "as.Date()"
Date[1:365069], 格式: "2019-01-01" "2019-01-01" "2019-01-01" "2019-01-01" "2019-01-01" ...
现在让检查数据的结构:str(raw_data)
'data.frame': 365069 观测值,12个变量:
$ trip_id : int 21742443 21742444 21742445 21742446 21742447 21742448 21742449
$ start_time : POSIXlt, 格式: "2019-01-01 00:04:37" "2019-01-01 00:08:13" ...
$ end_time : POSIXlt, 格式: "2019-01-01 00:11:07" "2019-01-01 00:15:34" ...
$ bikeid : int 2167 4386 1524 252 1170 2437 2708 2796 6205 3939 ...
$ tripduration : chr "390.0" "441.0" "829.0" "1,783.0" ...
.... 等等
将字符转换为整数并处理N/A
as.integer(value)
:这个函数用于将值转换为整数数据类型,以便可以进行计算。让看看代码。
raw_data$tripduration <- as.integer(raw_data$tripduration) # 会在这里得到一个惊喜
是否得到了一个惊喜警告?是的,那是意图。那是什么意思呢?这意味着代码会工作,但是有na(N/A)值。N/A是和R都不理解的值,所以需要处理它们。
有多种方法可以处理它们,比如用一些合适的值替换它们(一些有意义且不会破坏或影响数据的值)。这样做很容易,但这不是方法的问题,而是知识+直觉+经验的问题。将在这里只展示一种方法。也许,会为插值创建一个单独的博客。
现在,如果看到tripduration,它意味着旅行所花费的时间。如果看数据(str(raw_data)
),会看到两个列start_time
和end_time
。如果减去行程的结束时间和行程的开始时间(end_time-start_time
),应该得到行程持续时间。让检查否有相同的行程持续时间,如果有,将用end_time-start_time
替换tripduration。
tester <- 60*(raw_data$end_time - raw_data$start_time) # 60乘以转换分钟为秒
忽略输出行:分钟的时间差,因为明确地将其转换为秒。
哇!一个完美的匹配…
接下来,将tester分配给tripduration,替换旧值。
raw_data$tripduration <- tester
数据和时间的力量
现在可以使用start_time
(类型:POSIXlt日期)并找出工作日(“星期一”,“星期二”等),周数(从1月1日起的周数)和月份编号。当需要1月份的数据或按周分组的数据时,这很重要。
install.packages("lubridate")
library(lubridate)
raw_data$weekdays <- weekdays(raw_data$start_time) # 创建新列 weekdays
raw_data$week_number <- lubridate::week(raw_data$start_time) # 使用 lubridate 的 week 函数 (::)
raw_data$month_number <- month(raw_data$start_time)
str(raw_data)
太棒了!做到了。干得好,学会了如何创建列、更新它们、清理它们和转换它们。使用这些基本的东西,肯定会做出一些了不起的事情。祝好运!!!
在分析和特征工程中,还使用summary或describe函数来查看数据的统计信息。像:
install.packages("psych")
library(psych) # 使用 psych 使用 describe 函数
describe(dataset_dataframe) # 首先安装 psych
summary(dataset_dataframe)