r-使用mutate ifelse和rollappy根据连续变量的变化创建条件因子



tl;dr我需要说明促销是否基于价格随时间的下降。我对其他方法持开放态度。

我有一个价格数据框架,随着时间的推移,它被划分为几个分组因素。我的目标是为"each"商店中的每个"ITEM"检查过去7个日期的"PRICE"模式(如果存在(。如果观察值小于价格模式的10%,则在"促销"列中,如果不是0,则应填充1。

示例数据

dat <- data.frame(Date = sample(seq(as.Date('1999/01/01'), as.Date('2000/01/01'), by="day"), 10),
Item = rep(LETTERS[1:4], times = 10),
Store =  as.factor(sample(rep(c("NY","SYD","LON","PAR"), each = 10))),
Price = rnorm(n = 40, mean = 2.5, sd = 1))

到目前为止,我已经使用dplyr的group_split将项目和存储分组分解为单独的数据帧,以捕获所有条件。我认为我现在需要做的是mutate——使用ifelse语句和rollapply的新列。到目前为止,我已经尝试使用以下代码行。。。

data %>% mutate(Promotion = ifelse(rollapply(Price, 7, Mode <= Price*0.91,1,0)))

这将返回一条错误语句。。。

Error: Problem with `mutate()` input `PRMT_IND2`.
x comparison (5) is possible only for atomic and list types
i Input `PRMT_IND2` is `ifelse(...)`.

我真的不知道从这里到哪里去。如果你有时间,如果你能告诉我如何将其应用于group_split创建的所有组,以及如何将其缝合在一起,我也将不胜感激。

注意观察(日期/行(甚至在商店之间都没有,有些商店的人口不足7天。如果没有滚动应用程序就无法工作,我可以删除这些。但这会丢失相当大的数据。

我正在将此功能用于模式。。。

Mode <- function(x) {
ux <- unique(x)
ux[which.max(tabulate(match(x, ux)))]
}

也许您可以使用滚动平均值而不是模式。

library(dplyr)
library(zoo)
dat %>%
group_by(Item, Store) %>%
mutate(Promotion = as.integer(abs((Price - 
rollmeanr(Price, 7, fill = NA))/Price) > 0.1))

这将给NA的前6个值,如果Price比前7天的值变化超过10%,则给1,否则为0。还要注意,我们在这里取绝对值,所以如果价格上涨或下跌10%,它将给出1。

正如Ronah Shak所指出的,函数似乎不是最合适的选择。此外,请注意,使用制表将值转换为整数,这可能会对您的值产生问题。

关于这个错误,正如您正确猜测的那样,问题是您分割的数据并不总是有7个日期,因此带有width=7rollapply函数返回了一个错误。允许函数使用日期向量的长度OR 7(如果可用(可以解决问题。此外,您可以使用group_by应用您的函数,不需要拆分数据。

dat %>%
group_by(Store,Item)%>%
mutate(price_check = Price*0.91, 
Promotion = ifelse(rollapply(Price, width = min(length(Date),7), Mode)>=price_check,1,0))

最新更新