dplyr不同组的滞后

Mar*_*ebs 8 r dplyr

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

原来的df

这就是我想要的结果:

期望的结果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))
Run Code Online (Sandbox Code Playgroud)

非常感谢你!

Cat*_*ath 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
Run Code Online (Sandbox Code Playgroud)

other_lag确定的解释:对于每个观察,想法是查看组值,如果存在与当前组不同的任何组值,则在当前组之前,然后取最后一个值,否则,放置NA.

注意: 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
                               }))
Run Code Online (Sandbox Code Playgroud)


Fra*_*ank 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]]
Run Code Online (Sandbox Code Playgroud)

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

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

这个怎么运作:

:= 创建一个新列

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

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

x[!i, on=]是一种反连接,查找的行ix并返回x与匹配的行删除.

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

  • 查找的每一行ix使用的on=条件
  • 如果未on=找到完全匹配,则"滚动"到最后一on=列的最接近的先前值
  • vx表中返回

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


zoo*_*alk 2

我不完全确定我是否正确地回答了你的问题,但如果“自己”和“其他”指的是 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)
Run Code Online (Sandbox Code Playgroud)