如何根据条件选择R数据框中的连续行?

Posted

技术标签:

【中文标题】如何根据条件选择R数据框中的连续行?【英文标题】:How to select continuous rows in R data frame based on conditions? 【发布时间】:2018-10-25 15:45:02 【问题描述】:

我有一个数据框 df,它有 date 、 group 和 gap days 列。我想为一个组选择从最新日期(最大日期)开始间隔天数连续为 1 的所有行。如果 gap days 不等于 1 ,那么我们会忽略行,直到 gap days 不等于 1 为止。出于可重现的目的,我创建了当前的 df 和预期的 df...

df<-data.frame(Date=c("2018-10-15","2018-10-16","2018-10-17",
                  "2018-10-14","2018-10-15","2018-10-16","2018-10-18","2018-10-19",
                  "2018-10-18","2018-10-21","2018-10-23","2018-10-24","2018-10-27","2018-10-28"),Group=c("a","a","a","b","b","b","b","b","c","c","c","c","c","c"),Gap_Days=c(1,1,1,1,1,2,1,1,3,2,1,3,1,1))


df_expected<-data.frame(Date=c("2018-10-15","2018-10-16","2018-10-17","2018-10-18","2018-10-19","2018-10-27","2018-10-28"),Group=c("a","a","a", "b","b","c","c"),Gap_Days=c(1,1,1,1,1,1,1))

【问题讨论】:

df[rev(cumall(rev(df$Gap_Days == 1))),] 感谢您的评论,尽管它不符合我的要求...如果我按条件在组中应用上述代码...那么它只会显示所有内容为 1 的那些组...。如果只有一个条目,则不显示 根据您提供的测试数据,它完全符合您的预期输出。如果您还有其他条件,建议您更新测试数据以捕获这些条件。 谢谢....我会更新我的问题 这就是“单元测试”变得有价值的地方:找到错误,编写测试以突出显示该错误,然后修复错误。 【参考方案1】:

我的第一条评论与现在有效的唯一区别是对问题进行了分组。

基础R:

do.call("rbind", by(df, df$Group, FUN=function(d) d[rev(cumall(rev(d$Gap_Days == 1))),]))
#            Date Group Gap_Days
# a.1  2018-10-15     a        1
# a.2  2018-10-16     a        1
# a.3  2018-10-17     a        1
# b.7  2018-10-18     b        1
# b.8  2018-10-19     b        1
# c.13 2018-10-27     c        1
# c.14 2018-10-28     c        1

Tidyverse:

df %>%
  group_by(Group) %>%
  filter(rev(cumall(rev(Gap_Days == 1)))) %>%
  ungroup()
# # A tibble: 7 x 3
#   Date       Group Gap_Days
#   <fct>      <fct>    <dbl>
# 1 2018-10-15 a            1
# 2 2018-10-16 a            1
# 3 2018-10-17 a            1
# 4 2018-10-18 b            1
# 5 2018-10-19 b            1
# 6 2018-10-27 c            1
# 7 2018-10-28 c            1

【讨论】:

【参考方案2】:

这是tidyverse的一种方法

library(dplyr)
library(data.table)
df %>% 
   group_by(grp = rleid(Gap_Days), 
   ind = any(Date == max(.data$Date))) %>% 
   ungroup %>% 
   filter(grp == max(grp) & ind) %>% 
   select(-ind, -grp)
# A tibble: 3 x 2
#   Date       Gap_Days
#  <date>        <dbl>
#1 2018-10-19        1
#2 2018-10-20        1
#3 2018-10-21        1

如果 'Date' 列已经排序,那么我们只需要检查 'Gap_Days 中的 1 即可

i1 <- inverse.rle(within.list(rle(df$Gap_Days == 1), 
           values[lengths < max(lengths) & values] <- FALSE))
df[i1,, drop = FALSE]

【讨论】:

以上是关于如何根据条件选择R数据框中的连续行?的主要内容,如果未能解决你的问题,请参考以下文章

MySQL 在特定条件下返回最新和最长的连续行

基于正则表达式连接熊猫中的连续行

聚合 SQL 中的连续行

Pandas:如何根据特定列上特定值的条件选择数据框中的行[重复]

员工角色的连续行

根据条件过滤数据框中的数据