【问题标题】:R - remove rows from dataframe where difference is less than 30 daysR - 从数据框中删除差异小于 30 天的行
【发布时间】:2019-05-05 10:51:50
【问题描述】:

我的数据框是这样的

df <- read.table(text="
                 id          nr      date
    1            124         1       2017-01-01
    2            122         1       2017-01-03
    3            124         2       2017-01-04
    4            121         1       2017-02-05
    5            124         3       2017-02-06
    6            124         3       2017-04-06
", header=TRUE)

我必须从我的数据框中删除天数差异小于 30 天的行。我通常使用前导函数来执行此操作,然后计算天数差异,如果它低于限制,则将其删除。

但现在我想删除低于限制的每一行。不仅如此;如果日期之间的日期差异超过 30 天,那么我必须过滤所有低于限制的下一行。

换句话说,有第一行,行号 2 和 3 应该被删除,因为日期差只有几天。第 4 行和第 1 行之间的差异超过 30 天,因此不应删除,第 4 和第 5 行之间的差异小于 30 天,因此删除它,结果中应该存在 6,因为差异超过 30 天,所以开。

【问题讨论】:

  • 我不确定为什么对您通常的策略(确保您也保留第一行)进行小幅修改是行不通的。 df %&gt;%mutate(tmp = lag(date)) %&gt;% filter(date - tmp &gt; 30 | date == first(date)) %&gt;% select(-tmp) 是否给出了你想要的结果?

标签: r


【解决方案1】:

也许有更简单的算法,但这个可以做到。

remove_dates <- function(DF, col = "date", lim = 30){
  n <- nrow(DF)
  log_inx <- !logical(n)
  i <- 1
  j <- 2
  while(i < n & j <= n){
    d <- difftime(DF[j, col], DF[i, col], unit = "days")
    if(d < lim){
      log_inx[j] <- FALSE
      j <- j + 1
    }else{
      i <- j
      j <- j + 1
    }
  }
  DF[log_inx, ]
}

remove_dates(df)
#   id nr       date
#1 124  1 2017-01-01
#4 121  1 2017-02-05
#6 124  3 2017-04-06

请注意,上面的函数可以在包magrittr管道中使用,%&gt;%

library(dplyr)

df %>% remove_dates()
#   id nr       date
#1 124  1 2017-01-01
#4 121  1 2017-02-05
#6 124  3 2017-04-06

【讨论】:

  • 只是出于我自己的好奇,df %&gt;%mutate(tmp = lag(date)) %&gt;% filter(date - tmp &gt; 30 | date == first(date)) %&gt;% select(-tmp) 没有这样做的原因是什么?在 OP 提供的示例数据上,它们提供了相同的结果,所以我只是有点困惑有什么区别。
  • @duckmayr 好多了。我开始回答说我想不出更好的算法,你的应该是一个答案并且被接受。
  • 我会为任何潜在的未来观众添加它。感谢您回来;老实说,我认为我错过了 OP 想要的逻辑。
【解决方案2】:

使用dplyr 方法:

df <- read.table(text="
                 id          nr      date
    1            124         1       2017-01-01
    2            122         1       2017-01-03
    3            124         2       2017-01-04
    4            121         1       2017-02-05
    5            124         3       2017-02-06
    6            124         3       2017-04-06
", header=TRUE)

df$date <- as.Date(df$date)

library(dplyr)

df %>%
    mutate(tmp = lag(date)) %>%
    filter(date - tmp > 30 | date == first(date)) %>%
    select(-tmp)

#    id nr       date
# 1 124  1 2017-01-01
# 2 121  1 2017-02-05
# 3 124  3 2017-04-06

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-12-05
    • 2011-12-16
    • 1970-01-01
    • 2015-10-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-08-16
    相关资源
    最近更新 更多