使用R统计数据集中商品近3个月推广次数及代码问题排查
解决R中按商品统计近3个月推广次数的问题
我来帮你排查代码里的问题,然后给出能实现需求的正确写法~
代码问题分析
你的代码之所以会全返回0,或者单独统计时得到整个数据集行数,核心有三个问题:
sum()的使用逻辑错了:sum()是对整个向量求和,会返回一个单一值,而不是逐行为每个商品计算对应次数。你当前的写法会把全数据集的条件结果加总,比如sum(df$ItemNumber == df$ItemNumber)本质是统计所有TRUE的数量,也就是整个数据集的行数。- 日期处理完全错误:你的
PromotedDate应该是字符型(从示例格式判断),直接对字符型日期减100会导致类型混乱,转成Date后也是无效值;而且用100天近似三个月不够准确,应该用日期函数计算精确的三个月前日期。 - 条件判断矛盾:
df$PromotedDate < df$PromotedDate是同一向量自身比较,所有结果都是FALSE,这直接导致sum()的结果为0,所以所有行都返回0。
正确实现方案
我推荐用dplyr+lubridate的组合来处理,代码简洁高效,适配你的2800条数据规模:
第一步:加载并预处理数据
先安装并加载必要的包,把字符型日期转换成标准Date类型:
# 首次使用先安装包 install.packages(c("dplyr", "lubridate")) library(dplyr) library(lubridate) # 转换日期格式:mdy()自动识别MM/DD/YYYY格式 df <- df %>% mutate(PromotedDate = mdy(PromotedDate))
第二步:按商品分组统计近3个月推广次数
按ItemNumber分组后,逐行计算对应日期前三个月内的推广次数:
df <- df %>% group_by(ItemNumber) %>% mutate( # 计算当前日期往前推3个月的精确日期 three_months_ago = PromotedDate %m-% months(3), # 统计同商品中,推广日期在[three_months_ago, PromotedDate)之间的次数 # 如果想把当前日期的推广也算进去,把<改成<=即可 Number.Times.Promoted.Last.3.Months = sum(PromotedDate > three_months_ago & PromotedDate < PromotedDate, na.rm = TRUE) ) %>% ungroup()
如果你习惯用Base R写法
也可以用sapply()逐行遍历计算:
# 先转换日期格式 df$PromotedDate <- as.Date(df$PromotedDate, format = "%m/%d/%Y") # 逐行计算每个商品的近3个月推广次数 df$Number.Times.Promoted.Last.3.Months <- sapply(1:nrow(df), function(i) { current_item <- df$ItemNumber[i] current_date <- df$PromotedDate[i] three_months_back <- current_date - months(3) # 统计符合条件的行数 sum(df$ItemNumber == current_item & df$PromotedDate > three_months_back & df$PromotedDate < current_date, na.rm = TRUE) })
验证说明
拿你的示例数据来说,每个商品只有一次推广记录,所以新增列的值都会是0,符合预期。如果某个商品有多次推广(比如ItemA在2018-11-01和2018-12-31各有一次推广),那么2018-12-31这行的统计值会是1,因为2018-11-01落在2018-09-31(三个月前)到2018-12-31之间。
内容的提问来源于stack exchange,提问作者Mike
相关产品推荐
相关产品推荐

