【问题标题】:Filter (subset) by conditions in 2 columns in R (dplyr or otherwise)按 R 中 2 列中的条件过滤(子集)(dplyr 或其他)
【发布时间】:2018-01-24 20:30:11
【问题描述】:

给定一个数据集,例如:

set.seed(134)
df<- data.frame(ID= rep(LETTERS[1:5], each=2),
           condition=rep(0:1, 5),
           value=rpois(10, 3)
           )
df

       ID condition value
1   A         0     2
2   A         1     3
3   B         0     5
4   B         1     2
5   C         0     3
6   C         1     1
7   D         0     2
8   D         1     4
9   E         0     1
10  E         1     5

对于每个 ID,当 condition==0 的值小于 condition==1 的值时,我想保留两个观察值。当条件==0 的值大于条件==1 时,我只想保留条件==0 的行。

返回的子集应该是这样的:

 ID condition value
1   A         0     2
2   A         1     3
3   B         0     5
5   C         0     3
7   D         0     2
8   D         1     4
9   E         0     1
10  E         1     5

使用 dplyr 的第一步是:

df %>% group_by(ID) %>% 

但不知道从那里去哪里。

【问题讨论】:

    标签: r dplyr subset


    【解决方案1】:

    按字面意思翻译,

    library(dplyr)
    set.seed(134)
    
    df <- data.frame(ID = rep(LETTERS[1:5], each = 2),
                     condition = rep(0:1, 5),
                     value = rpois(10, 3))
    
    df %>% group_by(ID) %>% 
        filter(condition == 0 | 
                   (condition == 1 & value > value[condition == 0]))
    #> # A tibble: 8 x 3
    #> # Groups: ID [5]
    #>   ID    condition value
    #>   <fct>     <int> <int>
    #> 1 A             0     2
    #> 2 A             1     3
    #> 3 B             0     5
    #> 4 C             0     3
    #> 5 D             0     2
    #> 6 D             1     4
    #> 7 E             0     1
    #> 8 E             1     5
    

    这取决于每个组对condition == 0 的单一观察,但除此之外应该相当稳健。

    【讨论】:

    • 谢谢 - 这是最简单和最强大的解决方案......特别是,拥有“子条件”的能力......| (condition == 1 &amp; value &gt; value[condition == 0])是我不知道的部分。
    【解决方案2】:

    这可能不是最简单的方法,但应该可以按您的意愿工作。

    library(reshape2)
    df %>% 
        dcast(ID ~ condition, value.var = 'value') %>% # cast to wide format
        mutate(`1` = ifelse(`1` > `0`, `1`, NA)) %>% # turn 0>1 values as NA
        melt('ID') %>% # melt as long format
        arrange(ID) %>% # sort by ID
        filter(complete.cases(.)) # remove NA rows
    

    输出:

    ID variable value
    1  A        0     2
    2  A        1     3
    3  B        0     5
    4  C        0     3
    5  D        0     2
    6  D        1     4
    7  E        0     1
    8  E        1     5
    

    【讨论】:

    • 谢谢。这行得通,我曾考虑重塑数据以解决问题,但希望得到更直接、更有效的方法,正如@alistaire 提供的那样。
    【解决方案3】:

    您总是需要每个组中第一行的值。如果每个组中第二行的值大于第一行,您只需要它。

    这有效:

    df %>% 
      group_by(ID) %>% 
      filter(row_number() == 1 | value > lag(value))
    

    编辑:正如@a​​listaire 指出的那样,此方法取决于特定的顺序,这可能是一个好主意,可以保证如下:

    df %>% 
      arrange(ID, condition) %>%
      group_by(ID) %>% 
      filter(row_number() == 1 | value > lag(value))
    

    【讨论】:

    • lag 的使用取决于未明确设置的行顺序。事先使用arrange,这可能没问题。
    • @ngm 谢谢。我应该提供一个更真实的示例数据集,因为这个解决方案过于具体,无法应用于我的真实数据(它有 >2 个条件,其中一些条件每个 ID 可能发生 >1 次)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-01-25
    • 1970-01-01
    • 2019-10-20
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多