选择第一个积极事件

Posted

技术标签:

【中文标题】选择第一个积极事件【英文标题】:Selecting the first positive event 【发布时间】:2021-01-25 09:43:21 【问题描述】:

我正在苦苦思考如何仅使用基于日期的第一个正面测试来创建数据框的子样本。我将展示一个玩具示例。假设我有以下内容;

df = data.frame(guy = c("A", "B", "A", 'B', "C", "C"),
  test1 = c(1, 1, 0, 0, 1, 0),
                test2 = c(0, 1, 0, 1, 0, 0),
                test3 = c(0, 0, 1, 0, 0, 1),
                date = as.Date(c('1999-10-20', '1999-10-21', '1999-10-22', '1999-10-23', '1999-10-24', '1999-10-25')));df
   #guy test1 test2 test3       date
#1   A     1     0     0 1999-10-20
#2   B     1     1     0 1999-10-21
#3   A     0     0     1 1999-10-22
#4   B     0     1     0 1999-10-23
#5   C     1     0     0 1999-10-24
#6   C     0     0     1 1999-10-25

现在,我想过滤,根据最旧的 date 仅选择第一个阳性测试(即 test1|test2|test3 = 1)。在我的示例中,我会得到以下信息:

   #guy test1 test2 test3       date
#1   A     1     0     0 1999-10-20
#2   B     1     1     0 1999-10-21
#3   C     1     0     0 1999-10-24

数据框:

df = data.frame(guy = c("A", "B", "A", 'B', "C", "C"),
  test1 = c(1, 1, 0, 0, 1, 0),
                test2 = c(0, 1, 0, 1, 0, 0),
                test3 = c(0, 0, 1, 0, 0, 1),
                date = as.Date(c('1999-10-20', '1999-10-21', '1999-10-22', '1999-10-23', '1999-10-24', '1999-10-25')));df

任何提示我该怎么做?

【问题讨论】:

为什么sqlite被标记在这里? test1 列有字符串 A、B 和 C,您需要如何将其与 1 进行比较? 【参考方案1】:

使用dplyr::top_n 另一个选项是:

df = data.frame(guy = c("A", "B", "A", 'B', "C", "C"),
                test1 = c(1, 1, 0, 0, 1, 0),
                test2 = c(0, 1, 0, 1, 0, 0),
                test3 = c(0, 0, 1, 0, 0, 1),
                date = as.Date(c('1999-10-20', '1999-10-21', '1999-10-22', '1999-10-23', '1999-10-24', '1999-10-25')))

library(dplyr)

df %>% 
  filter(test1 | test2 | test3) %>% 
  group_by(guy) %>% 
  top_n(-1, date)
#> # A tibble: 3 x 5
#> # Groups:   guy [3]
#>   guy   test1 test2 test3 date      
#>   <chr> <dbl> <dbl> <dbl> <date>    
#> 1 A         1     0     0 1999-10-20
#> 2 B         1     1     0 1999-10-21
#> 3 C         1     0     0 1999-10-24

【讨论】:

【参考方案2】:

使用subset + ave + max.col 的基本 R 选项

subset(
  df,
  as.logical(
    ave(
      max.col(df[grepl("test\\d+", names(df))], "first"),
      guy,
      FUN = function(x) x == min(x)
    )
  ) & (test1|test2|test3)
)

给了

  guy test1 test2 test3       date
1   A     1     0     0 1999-10-20
2   B     1     1     0 1999-10-21
5   C     1     0     0 1999-10-24

【讨论】:

@akrun 是的,你的理解是对的。 OP 想找出test1test2test3(按guy 分组)中的第一个正值并获取该行 @akrun 奥基,我明白了。谢谢你纠正我。我会努力解决这个问题 @akrun 我想现在它会是一个安全的版本【参考方案3】:

dplyr 1.0.0 用于任何个您可以执行的test 列:

library(dplyr)

df %>%
  group_by(guy) %>%
  slice(which.max(rowSums(select(cur_data(), starts_with('test'))) > 0))


#   guy   test1 test2 test3 date      
#  <chr> <dbl> <dbl> <dbl> <date>    
#1 A         1     0     0 1999-10-20
#2 B         1     1     0 1999-10-21
#3 C         1     0     0 1999-10-24

以上假设您在每个 guy 中至少有一行,其中包含 1。如果不是这种情况,则意味着您可以拥有一个没有任何 1 的 guy,您可以使用 match

df %>%
  group_by(guy) %>%
  slice(match(TRUE, rowSums(select(cur_data(), starts_with('test'))) > 0))

【讨论】:

【参考方案4】:

另一种方法可以使用inner_join() 完成,并将数据重新整形为 long 以识别旧日期和值。代码如下:

library(tidyverse)
#Code
dfout <- df %>% inner_join(df %>% pivot_longer(-c(guy,date)) %>% group_by(guy,name) %>%
  filter(date==min(date) & value==1) %>% ungroup() %>%
  group_by(guy) %>%
  filter(!duplicated(value)) %>% select(-c(name,value)))

输出:

  guy test1 test2 test3       date
1   A     1     0     0 1999-10-20
2   B     1     1     0 1999-10-21
3   C     1     0     0 1999-10-24

【讨论】:

【参考方案5】:

base R 的选项

subset(df, seq_len(nrow(df)) == ave(seq_len(nrow(df)) *
       (test1|test2|test3), guy, FUN = min))
#   guy test1 test2 test3       date
#1   A     1     0     0 1999-10-20
#2   B     1     1     0 1999-10-21
#5   C     1     0     0 1999-10-24

【讨论】:

这是一个非常简单的基础 R 解决方案,喜欢它!【参考方案6】:

试试:

library(dplyr)
df %>% filter(test1 | test2 | test3 ) %>% 
       arrange(date) %>% group_by(guy) %>% 
       summarize(first(date),first(test1),first(test2),first(test3)) %>%
       ungroup

# A tibble: 3 x 5
  guy   `first(date)` `first(test1)` `first(test2)` `first(test3)`
  <chr> <date>                 <dbl>          <dbl>          <dbl>
1 A     1999-10-20                 1              0              0
2 B     1999-10-21                 1              1              0
3 C     1999-10-24                 1              0              0

【讨论】:

以上是关于选择第一个积极事件的主要内容,如果未能解决你的问题,请参考以下文章

带有 UIControlEvents.valueChanged 的​​日期选择器不适用于第一个值更改事件

select onchange事件,选择第一个时没反应

Mybatis学习第25节 -- 懒加载 积极与不积极

文本框事件仅触发第二次

选择表格第一行的输入

如何使用第一个下拉列表的 onChange 事件填充另一个下拉列表?