我发现了像this这样的类似问题,但不完全一样。这是我的问题,我有以下数据集:
SELECT
{} ON 0
,[Customer].[Customer Geography].[Country] ON 1
FROM
(
SELECT
Head
(
Order
(
NonEmpty
(
[Customer].[Customer Geography].[Country]
*
[Date].[Calendar].[Calendar Year]
,[Measures].[Internet Sales Amount]
)
,[Measures].[Internet Sales Amount]
,bdesc
)
,50
) ON 0
FROM [Adventure Works]
);
我想创建以下列:> ds
id begin end
1 1 2017-01-15 2017-01-17
2 1 2017-01-01 2017-01-03
3 2 2017-02-01 2017-02-28
4 4 2017-04-11 2017-05-11
5 3 2017-02-05 2017-02-10
6 4 2017-03-10 2017-03-20
7 1 2017-01-30 2017-02-03
8 3 2017-02-28 2017-03-09
9 4 2017-02-26 2017-03-05
,为具有相同check
值的每一行验证以下条件:
id
否则为ds[i,]$begin - ds[i-1,]$end < 30 => 1 # for each row i
。当它是该组的第一个元素时,则没有先前的信息,因此在这种情况下,新列0
的值也将始终为零。
与我看到的其他问题(通过:check
,ave
解决)的区别在于,我需要进行涉及后续行但不是同一列的计算。
以下是代码:
定义数据集
dplyr
对信息进行排序(我们需要使用for循环来获取当前解决方案)
id <- c("1", "1", "2", "4", "3", "4", "1", "3")
begin <- c("20170115", "20170101", "20170201",
"20170411",
"20170205", "20170310",
"20170130", "20170228"
)
end <- c("20170117", "20170103", "20170228",
"20170511",
"20170210", "20170320",
"20170203", "20170309"
)
ds <- data.frame(id = id, begin = as.Date(begin, "%Y%m%d"), end = as.Date(end, "%Y%m%d"))
现在使用for循环来分配控制变量:idx = order(rank(ds$id), ds$begin, decreasing = FALSE)
ds <- ds[idx,]
:
check
最后预期的输出:
ds$check <- numeric(nrow(ds))
ds$check <- NA_integer_
nrep <- -1
for (i in 1:nrow(ds)) {
rowi <- ds[i,]
if (nrep == -1) {# Setting the first element of ds
end.prev <- rowi$end
id.prev <- rowi$id
ds[i,]$check <- 0
nrep = 1
} else {
id.current <- rowi$id
if(id.prev == id.current) {
ds[i,]$check <- ifelse(rowi$begin - end.prev < 30, 1, 0)
} else {
ds[i,]$check <- 0
}
end.prev <- rowi$end
id.prev <- id.current
}
}
感谢任何提示。
答案 0 :(得分:1)
使用dplyr
,使用lag
可以轻松实现:
ds %>%
group_by(id) %>%
arrange(id, begin) %>%
mutate(check = c(0, as.numeric(begin - lag(end) < 30)[-1]))
给出:
Source: local data frame [8 x 4] Groups: id [4] id begin end check <fctr> <date> <date> <dbl> 1 1 2017-01-01 2017-01-03 0 2 1 2017-01-15 2017-01-17 1 3 1 2017-01-30 2017-02-03 1 4 2 2017-02-01 2017-02-28 0 5 3 2017-02-05 2017-02-10 0 6 3 2017-02-28 2017-03-09 1 7 4 2017-03-10 2017-03-20 0 8 4 2017-04-11 2017-05-11 1
说明:
group_by
,因此计算由id
完成。arrange
确保我们从最早的日期开始。check
s,第一个值为0
,begin
减去前一个end
是否小于30.我们使用as.numeric
将逻辑转换为数字。另见:vignette('window-functions')
。
注意:我认为每组的第一个值可以简单地保留在NA
,因为它确实是未知的或未定义的,这将简化为:
ds %>%
group_by(id) %>%
mutate(check = as.numeric(begin - lag(end, order_by = begin) < 30))
答案 1 :(得分:1)
使用data.table:
setDT(ds)[,New:=as.numeric(begin-shift(end,fill=0)<30),id]
使用dplyr:
ds%>%group_by(id)%>%mutate(new=as.numeric(begin-lag(end,default=0)<30))%>%arrange(id)