首页 文章

不同组的dplyr滞后

提问于
浏览
7

我试图使用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 回答

  • 6

    data.table的解决方案:

    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
                                   }))
    
  • 2

    另一个类似@ 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=] 是一个反连接,在 x 中查找 i 的行并返回 x 并删除匹配的行 .

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

    • 使用 on= 条件在 x 中查找 i 的每一行

    • 如果找不到完全匹配的 on= ,它"rolls"到最后 on= 列的最接近的前一个值

    • 它从 x 表返回 v

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

  • 7

    我不完全确定我是否正确地得到了你的问题,但如果“拥有”和“其他”指的是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)
    
  • 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 == ... operation . 下一个操作完成所有操作然后我们选择最后我们想要的变量 .

相关问题