向量化具有多个条件的 for 循环,循环遍历 R 中的数据帧
Vectorize a for loop with multiple conditions that loops through dataframe in R
我有一个包含 700 万行的大型数据集,我正在尝试遍历数据框的每一行并根据一组条件更改列中的值。
这会花费很多时间,我想知道是否可以对该过程进行矢量化,或者是否有更有效、更快速的方法来进行。我正在使用 R 代码
我的代码如下:
for(row in 1:nrow(tttotalCam2020)){
viewTime <- tttotalCam2020[row, "DAY_DATE"]
termCode <- tttotalCam2020[row, "TERM_CODE"]
if(termCode=='SP1'){
if(viewTime <= as.POSIXct("2020/01/31")){
tttotalCam2020[row,'COURSE_PERIOD']='Early'
}else if(as.POSIXct("2020/02/1") >= viewTime & viewTime <= as.POSIXct("2020/03/8")){
tttotalCam2020[row,'COURSE_PERIOD']='Mid'
}else{
tttotalCam2020[row,'COURSE_PERIOD']='Late'
}
}else if(termCode=='SP2'){
if(viewTime <=as.POSIXct("2020/03/31")){
tttotalCam2020[row,'COURSE_PERIOD']='Early'
}else if(as.POSIXct("2020/04/1")>=viewTime & viewTime <=as.POSIXct("2020/06/5")){
tttotalCam2020[row,'COURSE_PERIOD']='Mid'
}else{
tttotalCam2020[row,'COURSE_PERIOD']='Late'
}
}else {
if(viewTime <=as.POSIXct("2020/04/24")){
tttotalCam2020[row,'COURSE_PERIOD']='Early'
}else if(as.POSIXct("2020/04/25")>=viewTime & viewTime <=as.POSIXct("2020/05/31")){
tttotalCam2020[row,'COURSE_PERIOD']='Mid'
}else{
tttotalCam2020[row,'COURSE_PERIOD']='Late'
}
我认为您正在寻找 mapply()
函数。
https://www.rdocumentation.org/packages/base/versions/3.6.2/topics/mapply
使用 mapply()
您可以定义一个具有多个输入值(例如列中的条件)的函数,并且 运行 它不需要 for 循环。
如果您能分享我们可以测试的示例数据,我们会更容易提供帮助。
dplyr::case_when
解决方案可能如下所示:
library(dplyr)
tttotalCam2020 %>%
mutate(COURSE_PERIOD = case_when(
termCode == "SP1" & viewtime <= as.POSIXct("2020/01/31") ~ "Early",
termCode == "SP1" & viewtime <= as.POSIXct("2020/03/08") ~ "Mid",
# etc.
))
如果你有很多不同的 termCodes
,最好利用重复结构并做这样的事情,将所有日期放在一个 table 中,加入它到你的主要数据,然后你可以使用更清晰的代码来获得你的结果。这应该非常快,因为连接非常高效,然后您只需要做一个向量化计算。
library(lubridate)
lookup_table <- tribble(
~termCode, ~Early, ~Mid,
"SP1", 20200131, 20200308,
"SP2", 20200331, 20200605,
"SP3", 20200424, 20200531) %>%
mutate(across(Early:Mid, ymd)) #lubridate::ymd
tttotalCam2020 %>%
left_join(lookup_table) %>%
mutate(COURSE_PERIOD = case_when(
viewTime <= Early ~ "Early",
viewTime <= Mid ~ "Mid",
TRUE ~ "Late"
))
我有一个包含 700 万行的大型数据集,我正在尝试遍历数据框的每一行并根据一组条件更改列中的值。
这会花费很多时间,我想知道是否可以对该过程进行矢量化,或者是否有更有效、更快速的方法来进行。我正在使用 R 代码
我的代码如下:
for(row in 1:nrow(tttotalCam2020)){
viewTime <- tttotalCam2020[row, "DAY_DATE"]
termCode <- tttotalCam2020[row, "TERM_CODE"]
if(termCode=='SP1'){
if(viewTime <= as.POSIXct("2020/01/31")){
tttotalCam2020[row,'COURSE_PERIOD']='Early'
}else if(as.POSIXct("2020/02/1") >= viewTime & viewTime <= as.POSIXct("2020/03/8")){
tttotalCam2020[row,'COURSE_PERIOD']='Mid'
}else{
tttotalCam2020[row,'COURSE_PERIOD']='Late'
}
}else if(termCode=='SP2'){
if(viewTime <=as.POSIXct("2020/03/31")){
tttotalCam2020[row,'COURSE_PERIOD']='Early'
}else if(as.POSIXct("2020/04/1")>=viewTime & viewTime <=as.POSIXct("2020/06/5")){
tttotalCam2020[row,'COURSE_PERIOD']='Mid'
}else{
tttotalCam2020[row,'COURSE_PERIOD']='Late'
}
}else {
if(viewTime <=as.POSIXct("2020/04/24")){
tttotalCam2020[row,'COURSE_PERIOD']='Early'
}else if(as.POSIXct("2020/04/25")>=viewTime & viewTime <=as.POSIXct("2020/05/31")){
tttotalCam2020[row,'COURSE_PERIOD']='Mid'
}else{
tttotalCam2020[row,'COURSE_PERIOD']='Late'
}
我认为您正在寻找 mapply()
函数。
https://www.rdocumentation.org/packages/base/versions/3.6.2/topics/mapply
使用 mapply()
您可以定义一个具有多个输入值(例如列中的条件)的函数,并且 运行 它不需要 for 循环。
如果您能分享我们可以测试的示例数据,我们会更容易提供帮助。
dplyr::case_when
解决方案可能如下所示:
library(dplyr)
tttotalCam2020 %>%
mutate(COURSE_PERIOD = case_when(
termCode == "SP1" & viewtime <= as.POSIXct("2020/01/31") ~ "Early",
termCode == "SP1" & viewtime <= as.POSIXct("2020/03/08") ~ "Mid",
# etc.
))
如果你有很多不同的 termCodes
,最好利用重复结构并做这样的事情,将所有日期放在一个 table 中,加入它到你的主要数据,然后你可以使用更清晰的代码来获得你的结果。这应该非常快,因为连接非常高效,然后您只需要做一个向量化计算。
library(lubridate)
lookup_table <- tribble(
~termCode, ~Early, ~Mid,
"SP1", 20200131, 20200308,
"SP2", 20200331, 20200605,
"SP3", 20200424, 20200531) %>%
mutate(across(Early:Mid, ymd)) #lubridate::ymd
tttotalCam2020 %>%
left_join(lookup_table) %>%
mutate(COURSE_PERIOD = case_when(
viewTime <= Early ~ "Early",
viewTime <= Mid ~ "Mid",
TRUE ~ "Late"
))