【问题标题】:subset data based on multiple conditions基于多个条件的子集数据
【发布时间】:2019-07-22 03:18:21
【问题描述】:

我的 df 看起来像这样:

dfin <- 

ID   DAY   SIZE
1     -5    10
1     -2    15
1      0    10
1      1    20
2      5    20
3      -5   2
3      -4   10
3      1    15

我想对 DAY 行进行子集化,这样:如果主题的 DAY 值在 DAY 值中具有值 0(基线),则该主题的子集数据 DAY >= 0。如果某个主题的值以负数开头(并且没有 0 基线),则从壁橱中的负数 DAY 到该主题的正数 DAY 的子集。如果某个主题的 DAY 的值以正数开头(没有负数 DAY),则保留该主题的所有行。

输出应该是这样的:

dfout <- 

ID   DAY   SIZE
1      0    10
1      1    20
2      5    20
3      -4   10
3      1    15

我正在使用 RStudio。使用 data.table 的首选解决方案,如果可能(选项 1)或 dplyr(选项 2)。

【问题讨论】:

    标签: r dplyr data.table


    【解决方案1】:

    可能是这样的:

    library(data.table)
    setDT(dfin)[, 
            if(any(DAY==0)) .SD[DAY>=0]
            else if (DAY[1L] < 0) .SD[last(which(DAY < 0)):.N] 
            else .SD, 
        ID]
    

    输出:

       ID DAY SIZE
    1:  1   0   10
    2:  1   1   20
    3:  2   5   20
    4:  3  -4   10
    5:  3   1   15
    

    数据:

    library(data.table)
    dfin <- fread("ID   DAY   SIZE
    1     -5    10
    1     -2    15
    1      0    10
    1      1    20
    2      5    20
    3      -5   2
    3      -4   10
    3      1    15")
    

    【讨论】:

      【解决方案2】:

      我们可以编写一个包含所有条件的函数

      func <- function(value) {
          if (any(value == 0))
              which(value >= 0)
          else if (any(value < 0))
            max(which(value < 0)) :  max(which(value > 0))
          else seq_along(value)
      }
      

      并将其应用于每个组

      library(data.table)
      df[setDT(df)[, .I[func(DAY)], by = ID]$V1,]
      
      #   ID DAY SIZE
      #1:  1   0   10
      #2:  1   1   20
      #3:  2   5   20
      #4:  3  -4   10
      #5:  3   1   15
      

      dplyr 中我们可以使用slice

      library(dplyr)
      
      df %>%
        group_by(ID) %>%
        slice(func(DAY))
      
      #     ID   DAY  SIZE
      #   <int> <int> <int>
      #1     1     0    10
      #2     1     1    20
      #3     2     5    20
      #4     3    -4    10
      #5     3     1    15
      

      数据

      df <- structure(list(ID = c(1L, 1L, 1L, 1L, 2L, 3L, 3L, 3L), DAY = 
      c(-5L, -2L, 0L, 1L, 5L, -5L, -4L, 1L), SIZE = c(10L, 15L, 10L, 20L, 
      20L, 2L, 10L, 15L)), class = "data.frame", row.names = c(NA, -8L))
      

      【讨论】:

        【解决方案3】:

        我想对DAY 行进行子集化,这样:如果一个主题的DAY 值在DAY 值中具有值0(基线),那么该主题的子集数据DAY >= 0。如果某个主题的值以负数开头(并且没有 0 基线),则从壁橱的负数 DAY 到该主题的正数 DAY 的子集。如果某个主题的 DAY 的值以正数开头(没有负数 DAY),则保留该主题的所有行。

        也就是说,我们要严格删除某个 DAY 之前的任何内容,等于 0 或最接近的负 DAY:

        # find lower bound, if any
        lbDT = dfin[.(ID = unique(ID), DAY = 0L), on=.(ID, DAY), roll=TRUE, nomatch=0, 
          .(ID, first_DAY = x.DAY)
        ]
        
        # use an anti-join to drop observations before/below the lower bound
        dfin[!lbDT, on=.(ID, DAY < first_DAY)]
        
           ID DAY SIZE lb
        1:  1   0   10 -5
        2:  1   1   20 -5
        3:  2   5   20  5
        4:  3  -4   10 -5
        5:  3   1   15 -5
        

        【讨论】:

          猜你喜欢
          • 2018-12-06
          • 2016-03-19
          • 2011-12-21
          • 2019-10-22
          • 1970-01-01
          • 1970-01-01
          • 2020-10-23
          • 1970-01-01
          相关资源
          最近更新 更多