R:用于特征提取的编码循环函数有问题吗?
R: Trouble coding loop function for feature extraction?
我有两个向量:
EventDate <- c("2018-10-31", "2018-11-16", "2018-12-02")
ThirtyDaysPriorEvent <- c("2018-10-01", "2018-10-17", "2018-11-02")
我需要帮助为以下工作流程编写循环函数:
- 遍历向量以识别相同索引位置的日期,
并将它们存储在变量中。例如,第一对日期
将是 EventDate[1] & ThirtyDaysPriorEvent[1]。对于示例数据,值为“2018-10-31”和“2018-10-01”。
- 在 dplyr 的过滤器中使用变量作为日期参数
功能。在数据库中查询每个事件日期前 30 天发生的所有活动。将结果存储在名为 Activities30dys 的数据框中。
- 计算 Activities30dys 数据框中列的总和。
- 使用步骤 #3 中的计算值在事件数据框中创建一个新列。
这是我想要达到的结果:
事件数据框中名为 "d" 的新列源自活动数据框中 "x" 列中的聚合值。
date a b c d
2018-10-31 42 60.5 152.4 16.63
2018-11-16 54 54.1 151.6 16.63
2018-12-02 63 74.2 153.5 19.95
不过,据我所知,这是:
library(dplyr)
# identifies dates in the same index position for each vector & stores results in variables
e <- EventDate[1]
e30 <- ThirtyDaysPriorEvent[1]
# uses variables to filter Activities dataframe
Activities30Dys <- Activities %>%
filter(date > e30 & date < e)
# computes sum of x activity done 30 days prior to event date
sum(Activities30Dys$x, na.rm = TRUE)
# adds new column (d) to Events dataframe
Events %>%
mutate()
这是我的可重现数据:
Events <- structure(list(date = c("2018-10-31", "2018-11-16", "2018-12-02"
), a = c(42L, 54L, 63L), b = c(60.5, 54.1, 74.2), c = c(152.4,
151.6, 153.5)), .Names = c("date", "a", "b", "c"), row.names =
c(NA, 3L), class = "data.frame")
Activities <- structure(list(date = c("2018-09-18", "2018-09-19", "2018-10-21",
"2018-10-21", "2018-10-24", "2018-10-26", "2018-10-27", "2018-11-18",
"2018-11-19", "2018-11-21", "2018-11-24", "2018-11-26", "2018-11-27",
"2018-12-05"), x = c(3.43, 3.16, 3.2, 3.27, 3.74, 3.2, 3.22,
3.43, 3.16, 3.2, 3.74, 3.2, 3.22, 3.02), y = c(132L, 122L, 120L,
130L, 127L, 128L, 127L, 132L, 122L, 120L, 127L, 128L, 127L, 121L
)), .Names = c("date", "x", "y"), row.names = c(NA, 14L), class = "data.frame")
如何使用 R 最好地完成我的 objective?
我确信我们可以为此做一个完整的 dplyr 解决方案,但必须对数据进行重大重塑。
所以我提供了一个简单的 for 循环解决方案,主要是重复使用您编写的代码。小的修改是为了代码的易读性:
#-- Initialize d
Events$d <- NA
#-- Run loop
for (i in 1:nrow(Events)) {
e <- Events$date[i]
e30 <- e - 30
Events$d[i] <- Activities %>%
filter(between(date, e30, e)) %>%
summarize(x = sum(x, na.rm = TRUE)) %>%
pull()
}
这是一种方法。在众多之中。
extend_df <- function(events, priors, data) {
require(dplyr)
monthly <- list()
for (i in seq_along(events)) {
to <- events[i]
from <- priors[i]
monthly[[i]] <- data %>%
filter(date > from & date < to) %>%
summarise(n = sum(x)) %>%
pull(n)
}
return(monthly)
}
Events %>% mutate(d = extend_df(EventDate, ThirtyDaysPriorEvent, Activities))
date a b c d
1 2018-10-31 42 60.5 152.4 16.63
2 2018-11-16 54 54.1 151.6 16.63
3 2018-12-02 63 74.2 153.5 19.95
有几种方法可以解决它,具体取决于它如何适合您的工作流程。 purrr::map
函数族使得映射这些向量而不是循环变得容易。在这种情况下,map2
将同时映射到一对向量上。
我要注意的第一件事是,由于您正在处理日期,因此最好将它们视为日期并转换为 Date
class。
另一件事是,不清楚您在过滤时是否希望端点是 包含 或 独占 。我将 dplyr::between
用作 shorthand,但这将包括端点。我会让你根据需要调整。
一种方法是将 map2_dfr
的两个日期向量映射到 return 数据框,过滤 Activities
,按开始日期分组,然后汇总。这将为您提供一个数据框,然后您可以将其加入 Events
,前提是您已将其日期转换为真实的 Date
s。
library(dplyr)
library(purrr)
sums_df <- map2_dfr(as.Date(EventDate), as.Date(ThirtyDaysPriorEvent), function(e, e30) {
activities30dys <- Activities %>%
mutate(date = as.Date(date)) %>%
filter(between(date, e30, e)) %>%
group_by(date = e) %>%
summarise(d = sum(x, na.rm = T))
activities30dys
})
Events %>%
mutate(date = as.Date(date)) %>%
left_join(sums_df, by = "date")
#> date a b c d
#> 1 2018-10-31 42 60.5 152.4 16.63
#> 2 2018-11-16 54 54.1 151.6 16.63
#> 3 2018-12-02 63 74.2 153.5 19.95
另一种选择是执行类似的 map2
,但使用 map2_dbl
到 return 单个数值向量。然后,您可以 mutate
将其作为列添加到 Events
.
sums_dbl <- map2_dbl(as.Date(EventDate), as.Date(ThirtyDaysPriorEvent), function(e, e30) {
activities30dys <- Activities %>%
mutate(date = as.Date(date)) %>%
filter(between(date, e30, e))
sum(activities30dys$x, na.rm = T)
})
Events %>%
mutate(d = sums_dbl)
#> date a b c d
#> 1 2018-10-31 42 60.5 152.4 16.63
#> 2 2018-11-16 54 54.1 151.6 16.63
#> 3 2018-12-02 63 74.2 153.5 19.95
最后要注意的是,您无需存储事件日期和 30 天前日期的向量,您可以随时计算之前的日期。如果您已转换为 Date
,那么 e - 30
会为您提供 30 天前的日期,您可以像这样构建您的工作流程:
map(as.Date(EventDate), function(e) {
e30 <- e - 30
# ...
})
我有两个向量:
EventDate <- c("2018-10-31", "2018-11-16", "2018-12-02")
ThirtyDaysPriorEvent <- c("2018-10-01", "2018-10-17", "2018-11-02")
我需要帮助为以下工作流程编写循环函数:
- 遍历向量以识别相同索引位置的日期, 并将它们存储在变量中。例如,第一对日期 将是 EventDate[1] & ThirtyDaysPriorEvent[1]。对于示例数据,值为“2018-10-31”和“2018-10-01”。
- 在 dplyr 的过滤器中使用变量作为日期参数 功能。在数据库中查询每个事件日期前 30 天发生的所有活动。将结果存储在名为 Activities30dys 的数据框中。
- 计算 Activities30dys 数据框中列的总和。
- 使用步骤 #3 中的计算值在事件数据框中创建一个新列。
这是我想要达到的结果:
事件数据框中名为 "d" 的新列源自活动数据框中 "x" 列中的聚合值。
date a b c d
2018-10-31 42 60.5 152.4 16.63
2018-11-16 54 54.1 151.6 16.63
2018-12-02 63 74.2 153.5 19.95
不过,据我所知,这是:
library(dplyr)
# identifies dates in the same index position for each vector & stores results in variables
e <- EventDate[1]
e30 <- ThirtyDaysPriorEvent[1]
# uses variables to filter Activities dataframe
Activities30Dys <- Activities %>%
filter(date > e30 & date < e)
# computes sum of x activity done 30 days prior to event date
sum(Activities30Dys$x, na.rm = TRUE)
# adds new column (d) to Events dataframe
Events %>%
mutate()
这是我的可重现数据:
Events <- structure(list(date = c("2018-10-31", "2018-11-16", "2018-12-02"
), a = c(42L, 54L, 63L), b = c(60.5, 54.1, 74.2), c = c(152.4,
151.6, 153.5)), .Names = c("date", "a", "b", "c"), row.names =
c(NA, 3L), class = "data.frame")
Activities <- structure(list(date = c("2018-09-18", "2018-09-19", "2018-10-21",
"2018-10-21", "2018-10-24", "2018-10-26", "2018-10-27", "2018-11-18",
"2018-11-19", "2018-11-21", "2018-11-24", "2018-11-26", "2018-11-27",
"2018-12-05"), x = c(3.43, 3.16, 3.2, 3.27, 3.74, 3.2, 3.22,
3.43, 3.16, 3.2, 3.74, 3.2, 3.22, 3.02), y = c(132L, 122L, 120L,
130L, 127L, 128L, 127L, 132L, 122L, 120L, 127L, 128L, 127L, 121L
)), .Names = c("date", "x", "y"), row.names = c(NA, 14L), class = "data.frame")
如何使用 R 最好地完成我的 objective?
我确信我们可以为此做一个完整的 dplyr 解决方案,但必须对数据进行重大重塑。
所以我提供了一个简单的 for 循环解决方案,主要是重复使用您编写的代码。小的修改是为了代码的易读性:
#-- Initialize d
Events$d <- NA
#-- Run loop
for (i in 1:nrow(Events)) {
e <- Events$date[i]
e30 <- e - 30
Events$d[i] <- Activities %>%
filter(between(date, e30, e)) %>%
summarize(x = sum(x, na.rm = TRUE)) %>%
pull()
}
这是一种方法。在众多之中。
extend_df <- function(events, priors, data) {
require(dplyr)
monthly <- list()
for (i in seq_along(events)) {
to <- events[i]
from <- priors[i]
monthly[[i]] <- data %>%
filter(date > from & date < to) %>%
summarise(n = sum(x)) %>%
pull(n)
}
return(monthly)
}
Events %>% mutate(d = extend_df(EventDate, ThirtyDaysPriorEvent, Activities))
date a b c d
1 2018-10-31 42 60.5 152.4 16.63
2 2018-11-16 54 54.1 151.6 16.63
3 2018-12-02 63 74.2 153.5 19.95
有几种方法可以解决它,具体取决于它如何适合您的工作流程。 purrr::map
函数族使得映射这些向量而不是循环变得容易。在这种情况下,map2
将同时映射到一对向量上。
我要注意的第一件事是,由于您正在处理日期,因此最好将它们视为日期并转换为 Date
class。
另一件事是,不清楚您在过滤时是否希望端点是 包含 或 独占 。我将 dplyr::between
用作 shorthand,但这将包括端点。我会让你根据需要调整。
一种方法是将 map2_dfr
的两个日期向量映射到 return 数据框,过滤 Activities
,按开始日期分组,然后汇总。这将为您提供一个数据框,然后您可以将其加入 Events
,前提是您已将其日期转换为真实的 Date
s。
library(dplyr)
library(purrr)
sums_df <- map2_dfr(as.Date(EventDate), as.Date(ThirtyDaysPriorEvent), function(e, e30) {
activities30dys <- Activities %>%
mutate(date = as.Date(date)) %>%
filter(between(date, e30, e)) %>%
group_by(date = e) %>%
summarise(d = sum(x, na.rm = T))
activities30dys
})
Events %>%
mutate(date = as.Date(date)) %>%
left_join(sums_df, by = "date")
#> date a b c d
#> 1 2018-10-31 42 60.5 152.4 16.63
#> 2 2018-11-16 54 54.1 151.6 16.63
#> 3 2018-12-02 63 74.2 153.5 19.95
另一种选择是执行类似的 map2
,但使用 map2_dbl
到 return 单个数值向量。然后,您可以 mutate
将其作为列添加到 Events
.
sums_dbl <- map2_dbl(as.Date(EventDate), as.Date(ThirtyDaysPriorEvent), function(e, e30) {
activities30dys <- Activities %>%
mutate(date = as.Date(date)) %>%
filter(between(date, e30, e))
sum(activities30dys$x, na.rm = T)
})
Events %>%
mutate(d = sums_dbl)
#> date a b c d
#> 1 2018-10-31 42 60.5 152.4 16.63
#> 2 2018-11-16 54 54.1 151.6 16.63
#> 3 2018-12-02 63 74.2 153.5 19.95
最后要注意的是,您无需存储事件日期和 30 天前日期的向量,您可以随时计算之前的日期。如果您已转换为 Date
,那么 e - 30
会为您提供 30 天前的日期,您可以像这样构建您的工作流程:
map(as.Date(EventDate), function(e) {
e30 <- e - 30
# ...
})