我有以下示例数据框:
x
date product release
2012-01-01 A 0
2012-01-02 A 0
2012-01-03 A 0
2012-01-04 A 1
2012-01-05 A 0
2012-01-06 A 0
2012-01-07 A 0
2012-01-08 A 0
2012-01-09 A 0
2012-01-10 A 0
2012-01-11 A 0
2012-01-12 A 0
2012-01-01 Z 0
2012-01-02 Z 1
2012-01-03 Z 0
2012-01-04 Z 0
2012-01-05 Z 0
2012-01-06 Z 0
2012-01-07 Z 0
我希望遍历每一行并生成基于的dayssince列 自发布以来已经过了多少天。
要记住的几件事:
- 新产品发布= 1没有产品发布= 0
- 输出需要对日期和产品
所需的输出是:
x
date product release dayssince
2012-01-01 A 0 0
2012-01-02 A 0 0
2012-01-03 A 0 0
2012-01-04 A 1 1
2012-01-05 A 0 2
2012-01-06 A 0 3
2012-01-07 A 0 4
2012-01-08 A 0 5
2012-01-09 A 0 6
2012-01-10 A 0 7
2012-01-11 A 0 8
2012-01-12 A 0 9
2012-01-01 Z 0 0
2012-01-02 Z 1 1
2012-01-03 Z 0 2
2012-01-04 Z 0 3
2012-01-05 Z 0 4
2012-01-06 Z 0 5
2012-01-07 Z 0 6
我已经尝试了从ifelse语句和for循环到ddply的所有想法。
我能够解决问题的最简单方法是从概念上做到以下几点:
x$dayssince <- ifelse(x$release > 0, 1, 0)
- 然后检查每一天的每一行 - 如果dayssince == 1,那么1 - 如果是dayssince&lt; 1,然后检查上面的行 - 如果上面的行是&gt; 0,然后使用上面的行+ 1的值 - 这一切对产品而言都是独一无二的。
提前谢谢!
对于每年多次发布的相同产品,我希望获得自上次发布以来的天数。
例如:
x
date product release dayssince
2012-01-01 A 0 0
2012-01-02 A 0 0
2012-01-03 A 0 0
2012-01-04 A 1 1
2012-01-05 A 0 2
2012-01-06 A 0 3
2012-01-07 A 0 4
2012-01-08 A 0 5
2012-01-09 A 0 6
2012-01-10 A 1 1
2012-01-11 A 0 2
2012-01-12 A 0 3
2012-01-13 A 0 4
2012-01-14 A 0 5
...等 感谢国旗@DMC
答案 0 :(得分:2)
您可以尝试使用ave
base R
x$dayssince <- with(x, ave(release, cumsum(release), product,
FUN=function(y) cumsum(cumsum(y))))
或使用data.table
library(data.table)
setDT(x)[,dayssince:=cumsum(cumsum(release)) ,
.(product,cumsum(release))][]
# 1: 2012-01-01 A 0 0
# 2: 2012-01-02 A 0 0
# 3: 2012-01-03 A 0 0
# 4: 2012-01-04 A 1 1
# 5: 2012-01-05 A 0 2
# 6: 2012-01-06 A 0 3
# 7: 2012-01-07 A 0 4
# 8: 2012-01-08 A 0 5
# 9: 2012-01-09 A 0 6
# 10: 2012-01-10 A 1 1
# 11: 2012-01-11 A 0 2
# 12: 2012-01-12 A 0 3
# 13: 2012-01-01 Z 0 0
# 14: 2012-01-02 Z 1 1
# 15: 2012-01-03 Z 0 2
# 16: 2012-01-04 Z 0 3
# 17: 2012-01-05 Z 0 4
# 18: 2012-01-06 Z 0 5
# 19: 2012-01-07 Z 0 6
答案 1 :(得分:1)
解决方案使用dplyr
并创建一个中间变量release_num
:
library(dplyr)
x %>%
group_by(product) %>%
mutate(release_num = cumsum(release)) %>%
group_by(product, release_num) %>%
mutate(dayssince = cumsum(cumsum(release)))
答案 2 :(得分:0)
我的一个评论是,您要求一个逐行迭代的解决方案。&#39; 这不是 R < / strong>做事的方式。 R 适用于矢量 - 通常是列矢量。因此,任何解决方案都需要一些解决方法。您可以切换到 SAS 之类的内容,它可以明确地按行进行操作。
我的解决方案使用plyr
库,但它没有矢量化。因此它可能比某些替代品慢。
# given vector of release dates and output vector, produce "dayssince"
ds <- function(rel.dts, x) {
n <- length(rel.dts)
x[1:rel.dts[1]] <- 0
for (i in 2:n) {
x[(rel.dts[i-1]):(rel.dts[i]-1)] <- 0:(rel.dts[i]-rel.dts[i-1]-1)
}
x[rel.dts[n]:length(x)] <- 0:(length(x)-rel.dts[n])
return(x)
}
# use ds() on a given product
ds.prod <- function(dat) {
dat <- dat[order(dat$date, decreasing=FALSE),]
rel.dts <- which(dat$release ==1)
ds <- get("ds")
dat$daysince <- ds(rel.dts, x=vector("integer", length= nrow(dat)))
return(dat)
}
# split by product and run
require(plyr)
dat <- ddply(dat, .var="product", .fun= ds.prod)
答案 3 :(得分:0)
如果您的数据来自数据库,则可能更容易创建一个带有计算列的视图,用于计算自发布以来的天数。
我目前太累了,无法发布任何SQL代码,但如果这是一种你会考虑的方法,我明天可以提供一些示例代码。