【问题标题】:How to remove rows including sequential condition between two columns如何删除包含两列之间顺序条件的行
【发布时间】:2021-11-09 17:30:16
【问题描述】:

我正在尝试从我的数据框中删除这些因素,但仅限于特定日期之后的因素。这里我做了一个玩具例子:

我有一个test 数据框和一个检查数据框inspec。我想删除出现在inspec 中的var1 中的字母,但只删除inspec 中日期之后的行。例如,考虑

> test = data.frame(var1 = c("A", "B", "A", "B", "C","B", "A"), measure = c(6,7,8,6,10,1,0), date = as.Date(c("2021-01-02", "2021-01-03", "2021-01-04", "2021-01-05", "2021-01-06", "2021-01-07",  "2021-01-12")))
> test
  var1 measure       date
1    A       6 2021-01-02
2    B       7 2021-01-03
3    A       8 2021-01-04
4    B       6 2021-01-05
5    C      10 2021-01-06
6    B       1 2021-01-07
7    A       0 2021-01-12
> 
> inspec = data.frame(var1 = c("A", "C", "D", "A"), date = as.Date(c("2021-01-03", "2021-01-06", "2021-01-10", "2021-01-12")))
> inspec
  var1       date
1    A 2021-01-03
2    C 2021-01-06
3    D 2021-01-10
4    A 2021-01-12

那么,作为结果,我想得到:

> test
  var1 measure       date
1    A       6 2021-01-02
2    B       7 2021-01-03
3    B       6 2021-01-05
4    B       1 2021-01-07

请注意,只有在 inspec 数据框中指定的日期之后检查的 var1 中的 A 被排除在外。如果我不想在inspec 日期之前维护var1,我可以使用test= test[!(test$var1 %in% inspec$var1),]

任何提示我该怎么做?

【问题讨论】:

  • 我读错了问题,认为如果日期早于inspec,您想删除。

标签: r dataframe dplyr


【解决方案1】:

基础 R

## reduce `inspec` to the earliest date
inspec$date <- as.Date(inspec$date)
tmpinspec <- inspec[ave(as.integer(inspec$date), inspec$var1, FUN = function(z) z == min(z)) > 0,]
tmpinspec
#   var1       date
# 1    A 2021-01-03
# 2    C 2021-01-06
# 3    D 2021-01-10

tmp <- merge(test, tmpinspec, by = "var1", all.x = TRUE, suffixes = c("", ".y"))
tmp
#   var1 measure       date     date.y
# 1    A       6 2021-01-02 2021-01-03
# 2    A       8 2021-01-04 2021-01-03
# 3    A       0 2021-01-12 2021-01-03
# 4    B       7 2021-01-03       <NA>
# 5    B       6 2021-01-05       <NA>
# 6    B       1 2021-01-07       <NA>
# 7    C      10 2021-01-06 2021-01-06

tmp <- tmp[with(tmp, is.na(date.y) | date < date.y),]
# tmp$date.y <- NULL
# tmp
  var1 measure       date
# 1    A       6 2021-01-02
# 4    B       7 2021-01-03
# 5    B       6 2021-01-05
# 6    B       1 2021-01-07

dplyr

library(dplyr)
group_by(inspec, var1) %>%
  slice_min(date) %>%
  left_join(test, ., by = "var1", suffix = c("", ".y")) %>%
  filter(is.na(date.y) | date < date.y) %>%
  select(-date.y)
#   var1 measure       date
# 1    A       6 2021-01-02
# 2    B       7 2021-01-03
# 3    B       6 2021-01-05
# 4    B       1 2021-01-07

【讨论】:

  • 使用这种方法我会遇到一些不一致的情况,如果我在检查中有一行与另一个稍后的日期,因为在检查中var' 可以重复。
  • 在 dplyr 解决方案中添加 group_by :/
  • 你可以聚合inspec 以便每个组都保留其最早(或最晚)的日期吗?
  • @r2evans,是的,只有最早的事情
  • 更新为“最早”。
【解决方案2】:

我们可以加入var1并根据dates进行过滤,而数据按var1分组,只保留第一个匹配项。见下文;

library(dplyr)

test %>%
  left_join(inspec, by = "var1", suffix = c("", ".y")) %>%
  group_by(var1) %>% 
  filter(is.na(date.y) | date < first(date.y)) %>% 
  select(-date.y) %>% 
  group_by_all() %>% 
  slice(1)

#> # A tibble: 4 x 3
#> # Groups:   var1, measure, date [4]
#>   var1  measure date      
#>   <fct>   <dbl> <date>    
#> 1 A           6 2021-01-02
#> 2 B           1 2021-01-07
#> 3 B           6 2021-01-05
#> 4 B           7 2021-01-03

这是r2evans's answer 的变体。

【讨论】:

    【解决方案3】:

    使用data.table,我们也可以使用merge然后filter:

    library(data.table)
    test <- setDT(test); inspec <- setDT(inspec)
    test <- merge(test, inspec, by = "var1", all.x = TRUE, suffixes = c("", ".y"))
    
    test <- test[date < date.y | !is.na(date.y), .(var1, measure, date)]
    

    【讨论】:

    • 这返回了以下错误:Error in .(var1, measure, date) : could not find function "."
    猜你喜欢
    • 1970-01-01
    • 2016-12-02
    • 2022-01-20
    • 2022-01-10
    • 2017-08-31
    • 1970-01-01
    • 1970-01-01
    • 2015-02-05
    • 2018-12-10
    相关资源
    最近更新 更多