dplyr:在使用group_by()时,lead()和lag()的结果不正确

58

我想在每个分组中找到lead()和lag()元素,但是得到了一些错误的结果。

例如,数据如下所示:

library(dplyr)
df = data.frame(name=rep(c('Al','Jen'),3),
                score=rep(c(100, 80, 60),2))
df

数据:

  name score
1   Al   100
2  Jen    80
3   Al    60
4  Jen   100
5   Al    80
6  Jen    60

现在我想要找到每个人的lead()和lag()分数。如果我使用arrange()进行排序,我可以得到正确的答案:

df %>%
  arrange(name) %>%
  group_by(name) %>%
  mutate(next.score = lead(score),
         before.score = lag(score) )

输出1:

Source: local data frame [6 x 4]
Groups: name

      name score next.score before.score
    1   Al   100         60           NA
    2   Al    60         80          100
    3   Al    80         NA           60
    4  Jen    80        100           NA
    5  Jen   100         60           80
    6  Jen    60         NA          100

没有使用 arrange() 函数,结果是错误的:

df %>%
  group_by(name) %>%
  mutate(next.score = lead(score),
         before.score = lag(score) )

输出2:

Source: local data frame [6 x 4]
Groups: name

  name score next.score before.score
1   Al   100         80           NA
2  Jen    80         60           NA
3   Al    60        100           80
4  Jen   100         80           60
5   Al    80         NA          100
6  Jen    60         NA           80
例如,在第一行中,Al的next.score应该是60(第三行)。
有人知道为什么会发生这种情况吗?为什么arrange()会影响结果(不仅仅是关于顺序的值)?谢谢~

我无法重现。你使用的R版本是哪个?我在Windows 7上使用R 3.1.2得到1 Al 100 60 NA - Panagiotis Kanavos
1
我可以重现奇怪的结果(0.4.1.9000)。我认为(在快速、睡眼惺忪地查看函数调用系列源代码后),这是因为底层代码按实际整体行索引而不是相对行索引进行操作。这可能解释了 lead(我认为 pmin 是异常发生的位置),但不确定 lag 发生了什么(没有查看那里)。 - hrbrmstr
8
最新版本0.4.1的dplyr中似乎存在一个错误,已经在这里报告过了。 - alex23lemm
@hrbrmstr 不,只有0似乎比其他任何镜像都要落后。而且我现在也遇到了同样的错误。 - Panagiotis Kanavos
我明白了,谢谢!我想现在可以使用arrange()先对数据进行排序以避免这个问题。 - YJZ
显示剩余4条评论
3个回答

55

看起来你需要在lag和lead函数中传递额外的参数。当我运行不带arrange但添加了order_by的函数时,一切似乎正常。

df %>%
group_by(name) %>%
mutate(next.score = lead(score, order_by=name),
before.score = lag(score, order_by=name))

输出:

  name score next.score before.score
1   Al   100         60           NA
2  Jen    80        100           NA
3   Al    60         80          100
4  Jen   100         60           80
5   Al    80         NA           60
6  Jen    60         NA          100

我的sessionInfo()函数:

R version 3.1.1 (2014-07-10)
Platform: x86_64-w64-mingw32/x64 (64-bit)

locale:
[1] LC_COLLATE=Polish_Poland.1250  LC_CTYPE=Polish_Poland.1250        LC_MONETARY=Polish_Poland.1250
[4] LC_NUMERIC=C                   LC_TIME=Polish_Poland.1250    

attached base packages:
[1] stats     graphics  grDevices utils     datasets  methods   base     

other attached packages:
[1] dplyr_0.4.1

loaded via a namespace (and not attached):
[1] assertthat_0.1  DBI_0.3.1       lazyeval_0.1.10 magrittr_1.5                parallel_3.1.1  Rcpp_0.11.5    
[7] tools_3.1.1 

4
我正在处理类似于滞后的案例,不过有一个变化——需要按多个列进行分组和排序!如果在 group_by 和 order_by 中有多个列,答案会有多大的不同?我尝试了传递向量,但没有帮助。 - Akshay Rane

24
可能会出现使用stats::lag的情况(例如在使用session包恢复环境时)。当作为问题中使用时,它不会产生错误,因此很容易被忽略。通过简单地输入lag、使用conflicted包或通过调用dplyr::lag来消除函数调用的歧义,进行双重检查。
同样,可能会发生plyr::mutate的情况,如果你在当前session中加载了plyr包,请确保同时调用dplyr::mutate

2
许多软件包都有一个滞后函数 - 正如这个评论所述,除非您只依赖于一小组软件包或基本的R + dplyr,否则验证/消歧是至关重要的。 - HoneyBuddha
4
在发现了一篇神奇的回复强调dplyr:mutate和dplyr:lag之前,我浪费了最近的两个小时试图理解一个原本应该运行的代码突然出错的问题。这需要更多的关注。谢谢您。 - Bob
再次重申其他人所说的。花了这么长时间纠结一个非常简单的代码片段为什么突然不起作用了。非常令人沮丧!你的答案如此简单,却很容易被忽视,并解决了问题!!!谢谢 - DataMonkey

6

当你只有一个分组变量时,使用order_by是很好的选择。但如果有多个分组变量,我没有找到任何解决方案,除了写入和读取表格来消除分组变量。这对我来说效果不错,但其效率取决于表格的大小。


4
为了能使用order_by,我为这个案例创建了一个虚拟的分组变量:mutate(grouping=sprintf("%04d-%04d",var1,var2)),然后计算下一个得分:mutate(next.score = lead(score, order_by=grouping) %>% select(-grouping)。请注意,这里的翻译尽可能保留了原文意思和结构,同时增加了可读性和易懂性。 - Quantum7

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接