因此,我有大约2800个观测值的数据集。标头看起来像这样:
ItemName ItemNumber PromotedDate
ItemA 14321 12/31/2018
ItemB 14335 11/18/2018
ItemC 14542 10/05/2018
我希望能够向该数据集Number.Times.Promoted.Last.3.Months
添加一个新列,该列将计算在PromotedDate
变量的最后三个月中数据集中每个项目存在多少次。 / p>
我尝试创建一些代码(如下),但是每行返回0。当我尝试使用商品编号进行尝试时,我得到了整个数据集中的观测数量。
df$Number.Times.Promoted.Last.Three.Months <- sum(df$ItemNumber == df$ItemNumber &
df$PromotedDate < df$PromotedDate &
df$PromotedDate > (as.Date(df$PromotedDate - 100)),
na.rm=TRUE)))
我很想让代码返回自PromotedDate
变量以来过去3个月中提升数据集中每个项目的实际次数,并将其附加到数据的每一行(df
)。希望能帮助您找出我做错了什么。谢谢!
答案 0 :(得分:0)
注意:在链接的文件中有一个错字,第一个ItemB
以小写的i
开始。即使未更正,下面的代码也可以工作。
我发现以下解决方案有点复杂,但是确实可以解决问题。
library(lubridate)
fun <- function(x){
ifelse(month(x) == 12 & day(x) == 31,
x - days(31 + 30 + 31),
x - months(3)
)
}
df <- readxl::read_xlsx("example_20190519.xlsx")
df$PromotedDate <- as.Date(df$PromotedDate)
sp <- split(df, tolower(df$ItemName))
res <- lapply(sp, function(DF){
tmp <- as.Date(fun(DF$PromotedDate), origin = "1970-01-01")
sapply(seq_len(nrow(DF)), function(i){
sum(DF$PromotedDate[i] > DF$PromotedDate & DF$PromotedDate > tmp[i])
})
})
df$New.3.Months <- NA
for(nm in names(res)) {
df$New.3.Months[tolower(df$ItemName) == nm] <- res[[nm]]
}
现在测试以查看结果是否与示例.xlsx
文件中的结果相同。
all.equal(df$Times.Promoted.Last.3.Months, df$New.3.Months)
#[1] TRUE
最后的清理。
rm(sp)
答案 1 :(得分:0)
这是一个可以简化的解决方案,它依赖于dplyr
和fuzzyjoin
。
首先,我将日期定义为90天前**,然后将其与列表本身一起加入,并在每个商品匹配中输入促销日期为“自90天之前”和“直到当前日期”的促销日期。每个项目日期的行数是90天内的促销数量。通过减去代表自己的行,我们可以得出先前促销的次数。
**“提前90天”比“提前3mo”更简单,长度各不相同,并且在某些日期可以争论:5月30日之前的3个月是什么?
预备
library(dplyr); library(fuzzyjoin); library(lubridate)
df <- readxl::read_excel(
"~/Downloads/example_20190519.xlsx",
col_types = c("text", "numeric", "date", "numeric"))
df_clean <- df %>% select(-Times.Promoted.Last.3.Months)
解决方案
df_clean %>%
mutate(PromotedDate_less90 = PromotedDate - days(90)) %>%
# Pull in all matches (including current row) with matching Item and Promoted Date
# that is between Promoted Date and 90 days prior.
fuzzy_left_join(df_clean,
by = c("ItemName" = "ItemName",
"ItemNumber" = "ItemNumber",
"PromotedDate_less90" = "PromotedDate",
"PromotedDate" = "PromotedDate"),
match_fun = list(`==`, `==`, `<=`, `>=`)
) %>%
group_by(ItemName = ItemName.x,
ItemNumber = ItemNumber.x,
PromotedDate = PromotedDate.x) %>%
summarize(promotions_in_prior_90d = n() - 1) %>%
ungroup()
输出(顺序不同,但目标匹配)
# A tibble: 12 x 4
ItemName ItemNumber PromotedDate promotions_in_prior_90d
<chr> <dbl> <dttm> <dbl>
1 ItemA 10021 2018-09-19 00:00:00 0
2 ItemA 10021 2018-10-15 00:00:00 1
3 ItemA 10021 2018-11-30 00:00:00 2
4 ItemA 10021 2018-12-31 00:00:00 2
5 itemB 10024 2018-12-15 00:00:00 0
6 ItemB 10024 2018-04-02 00:00:00 0
7 ItemB 10024 2018-06-05 00:00:00 1
8 ItemB 10024 2018-12-01 00:00:00 0
9 ItemC 19542 2018-07-20 00:00:00 0
10 ItemC 19542 2018-11-17 00:00:00 0
11 ItemC 19542 2018-12-01 00:00:00 1
12 ItemC 19542 2018-12-14 00:00:00 2