dplyr不同组的滞后

时间:2018-04-18 11:04:55

标签: r dplyr

我正在尝试使用dplyr来修改包含变量的相同组滞后的列以及其他组(其中一个)的滞后。 编辑:对不起,在第一版中,我通过在最后一秒按日期重新排列来搞砸了订单。

Original df

这就是我想要的结果:

Desired Outcome df 这是一个最小的代码示例:

library(tidyverse)

set.seed(2)
df <-
  data.frame(
    x =  sample(seq(as.Date('2000/01/01'), as.Date('2015/01/01'), by="day"), 10),
    group = sample(c("A","B"),10,replace = T),
    value = sample(1:10,size=10)
  ) %>% arrange(x)

df <- df %>%
  group_by(group) %>%
  mutate(own_lag = lag(value))


df %>% data.frame(other_lag = c(NA,1,2,7,7,9,10,10,8,6))

非常感谢!

4 个答案:

答案 0 :(得分:7)

的解决方案:

library(data.table)

# to create own lag: 
setDT(df)[, own_lag:=c(NA, head(value, -1)), by=group]

# to create other group lag: (the function works actually outside of data.table, in base R, see N.B. below)
df[, other_lag:=sapply(1:.N, 
                       function(ind) {
                          gp_cur <- group[ind]
                          if(any(group[1:ind]!=gp_cur)) tail(value[1:ind][group[1:ind]!=gp_cur], 1) else NA
                       })]

df
 #            x group value own_lag other_lag
 #1: 2001-12-08     B     1      NA        NA
 #2: 2002-07-09     A     2      NA         1
 #3: 2002-10-10     B     7       1         2
 #4: 2007-01-04     A     5       2         7
 #5: 2008-03-27     A     9       5         7
 #6: 2008-08-06     B    10       7         9
 #7: 2010-07-15     A     4       9        10
 #8: 2012-06-27     A     8       4        10
 #9: 2014-02-21     B     6      10         8
#10: 2014-02-24     A     3       8         6

other_lag判断的解释:对于每次观察,想法是查看组值,如果有任何组值与当前组不同,则在当前组之前,然后取最后一组价值,否则,把NA。

N.B。: other_lag可以在不需要data.table的情况下创建:

df$other_lag <- with(df, sapply(1:nrow(df), 
                                function(ind) {
                                 gp_cur <- group[ind]
                                 if(any(group[1:ind]!=gp_cur)) tail(value[1:ind][group[1:ind]!=gp_cur], 1) else NA
                               }))

答案 1 :(得分:6)

另一种类似于@ Cath's的数据表:

library(data.table)
DT = data.table(df)
DT[, vlag := shift(value), by=group]
DT[, volag := .SD[.(chartr("AB", "BA", group), x - 1), on=.(group, x), roll=TRUE, x.value]]

这假定A和B是唯一的组。如果有更多...

DT[, volag := DT[!.BY, on=.(group)][.(.SD$x - 1), on=.(x), roll=TRUE, x.value], by=group]

工作原理:

:=创建一个新列

DT[, col := ..., by=]每个by=组分别执行任务,基本上作为循环。

  • 循环当前迭代的分组值位于命名列表.BY中。
  • 当前循环迭代使用的数据子集是data.table .SD

x[!i, on=]是一种反加入,在i中查找x行并返回x并删除匹配的行。

x[i, on=, roll=TRUE, x.v] ...

  • 使用i条件在x中查找on=的每一行
  • 如果未找到完全匹配的on=,则会“滚动”到最后on=列的最近值
  • v
  • 返回x

有关详细信息和直觉,请在键入library(data.table)时查看显示的启动消息。

答案 2 :(得分:2)

我不完全确定我是否正确地提出了您的问题,但是如果&#34;拥有&#34;和&#34;其他&#34;指的是A组和B组,那么这可能就是诀窍。我强烈认为有更优雅的方法可以做到这一点:

df.x <-  df %>% 
  dplyr::group_by(group) %>% 
  mutate(value.lag=lag(value)) %>% 
  mutate(index=seq_along(group)) %>% 
  arrange(group)

df.a <- df.x %>%
  filter(group=="A") %>% 
  rename(value.lag.a=value.lag)

df.b <- df.x %>% 
  filter(group=="B") %>% 
  rename(value.lag.b = value.lag)

df.a.b <- left_join(df.a, df.b[,c("index", "value.lag.b")], by=c("index"))

df.b.a <- left_join(df.b, df.a[,c("index", "value.lag.a")], by=c("index"))

df.x <- bind_rows(df.a.b, df.b.a)

答案 3 :(得分:2)

试试这个:(仅管道方法)

  library(zoo)
  df %>%
     mutate(groupLag = lag(group),
         dupLag = group == groupLag) %>%
     group_by(dupLag) %>%
     mutate(valueLagHelp = lag(value)) %>%
     ungroup() %>%
     mutate(helper = ifelse(dupLag == T, NA, valueLagHelp)) %>%
     mutate(helper = case_when(is.na(helper) ~ na.locf(helper, na.rm=F),
                                   TRUE ~ helper)) %>%
     mutate(valAfterLag = lag(dupLag)) %>%
     mutate(otherLag = ifelse(is.na(lag(valueLagHelp)), lag(value), helper)) %>%
     mutate(otherLag = ifelse((valAfterLag | is.na(valAfterLag)) & !dupLag, 
     lag(value), otherLag)) %>% 
     select(c(x, group, value, ownLag, otherLag))

抱歉这个烂摊子。 它的作用是它首先创建一个组滞后并为该组等于其滞后的情况创建一个辅助变量(即当两个“A”后续时。然后它按此辅助变量分组并分配给所有值为dupLag == F正确的值。现在我们需要处理dupLag == T的那些。

所以,取消组合。我们需要一个新的滞后值助手,它将所有dupLag == T分配给NA,因为它们尚未正确分配。

接下来是我们在助手中为所有NA分配最后一个非NA值。 这不是全部,因为我们仍然需要处理一些dupLag == F数据点(当你查看完整的tibble时你会得到它)。首先,我们基本上只用第一个mutate改变第二个数据点(otherLag == ...操作。下一个操作完成所有操作然后我们选择我们最终想要拥有的变量。