dplyr::filter() 基于 dplyr::lag() 进行筛选,但不丢失第一个数值。

4

当我根据lag()函数过滤数据集时,每个组的第一行会丢失(因为这些行没有lag值)。如何避免这种情况,以便保留第一行,尽管它们没有任何lag值?

ds <- 
  structure(list(mpg = c(21, 21, 21.4, 18.7, 14.3, 16.4), cyl = c(6, 
  6, 6, 8, 8, 8), hp = c(110, 110, 110, 175, 245, 180)), class = c("tbl_df", 
  "tbl", "data.frame"), row.names = c(NA, -6L), .Names = c("mpg", 
  "cyl", "hp"))

# example of filter based on lag that drops first rows
ds %>% 
  group_by(cyl) %>% 
  arrange(-mpg) %>% 
  filter(hp <= lag(hp))

1
lag(hp,default = hp[1])? - joran
@joran,以这种方式操作默认参数是一个好的解决方案,并且可以在等效性不足的情况下更新为“filter(hp > lag(hp, default = hp[1] - 1))”。 - Joe
2个回答

4

使用 filter(hp <= lag(hp)) 会排除那些 lag(hp)NA 的行。你可以改为筛选不等式或者 lag(hp),就像每个组的前几行一样。

我加入了 prev = lag(hp) 来创建一个独立的变量来表示滞后值,仅仅是为了更清晰和方便调试。

library(tidyverse)

ds %>%
    group_by(cyl) %>%
    arrange(-mpg) %>%
    mutate(prev = lag(hp)) %>%
    filter(hp <= prev | is.na(prev))

这将产生以下结果:
# A tibble: 4 x 4
# Groups:   cyl [2]
    mpg   cyl    hp  prev
  <dbl> <dbl> <dbl> <dbl>
1  21.4    6.  110.   NA 
2  21.0    6.  110.  110.
3  21.0    6.  110.  110.
4  18.7    8.  175.   NA 

3

由于 OP 所需的是与以前的值使用小于等于符号<=,因此使用带有 default = +Inflag 将足以满足其需求。

另外,在 dplyr 链中不需要单独使用 arrange,因为 lag 提供了选择 order_by 的选项。

因此,解决方案可以写成:

ds %>% 
  group_by(cyl) %>% 
  filter(hp <= lag(hp, default = +Inf, order_by = -mpg))

#Below result is in origianl order of the data.frame though lag was calculated 
#in ordered value of mpg
# # A tibble: 4 x 3
# # Groups: cyl [2]
#     mpg   cyl    hp
#    <dbl> <dbl> <dbl>
# 1  21.0  6.00   110
# 2  21.0  6.00   110
# 3  21.4  6.00   110
# 4  18.7  8.00   175

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