【问题标题】:Selecting rows based on multiple conditions根据多个条件选择行
【发布时间】:2018-03-02 15:29:13
【问题描述】:

我有一个 df

set.seed(123)
df <- data.frame(loc.id = rep(1:9, each = 9), month = rep(1:9,times = 9), 
                 x = runif(81, min = 0, max = 5))

这是一个有 9 个位置的数据框。对于每个位置,我有 9 个月,每个月都有一个 x 值。

对于每个位置,我想根据以下条件选择一个月:

1) 检查哪些月份(不包括第 9 个月)的 x > 1,然后选择最接近第 9 个月的月份。 例如,如果对于位置 1,x 的值为

  4.56, 3.41, 0.82, 2.31, 3.75, 4.75, 1.22, 2.98, 1.17

那么第 1、2、4、5、6、7、8 个月的 x > 1 并且从这些月份中,第 8 个月最接近第 9 个月。因此将选择第 8 个月

2) 如果没有一个月份的 x > 1,则只需选择具有最高 x 值的月份。例如:

如果对于一个位置,x 是

  0.8, 0.6, 0.95, 0.4, 0.88, 0.7, 0.6, 0.45, 0.3

然后将选择第 3 个月 (x = 0.95)

我试过了:

  library(dplyr)
  df %>% filter(month != 9) %>% # removes the 9 month so that only the 8 months are evaluated 
        group_by(loc.id) %>% 
        mutate(select.month = x > 1) %>% # mark those months where x > 1
        filter(select.month == TRUE) %>% # select those months where x > 1 is true
        mutate(dif = 9 - month) %>%# subtract each month from 9 to check which one is closest to 9
        summarise(month.id = min(dif)) # select the months which is closest to month 9

但是,在上述功能中,我无法检查所有月份都有的位置 值小于 1。我的问题是如何更改上面的代码以在 x 都不是 > 1 时也检查条件 2

【问题讨论】:

    标签: r if-statement dplyr data.table


    【解决方案1】:
    set.seed(123)
    > df <- data.frame(loc.id = rep(1:9, each = 9), month = rep(1:9,times = 9), 
                      x = runif(81, min = 0, max = 5))
    > set.seed(123)
    > df=rbind(df,cbind(loc.id=10,month=1:9 , x=runif(9)))
    
    
    
    
    > df%>%group_by(loc.id)%>%mutate(x=replace(x,9,0),y=cumsum(x>1))%>%
    +     summarise(y=ifelse(all(!y),which.max(x),which.max(y)))
    # A tibble: 10 x 2
       loc.id     y
        <dbl> <int>
     1      1     8
     2      2     8
     3      3     8
     4      4     7
     5      5     8
     6      6     8
     7      7     7
     8      8     8
     9      9     7
    10     10     5
    

    【讨论】:

      【解决方案2】:

      我稍微修改了您的数据框,因为没有任何loc.ids 只有几个月小于 1 的情况。

      df %>% 
        group_by(loc.id) %>%
        filter(month != 9) %>% 
        mutate(all_x_less_1 = all(x < 1)) %>% 
        filter(all_x_less_1 | x > 1) %>% 
        filter(month == if_else(all_x_less_1, month[which.max(x)], month[which.min(9 - month)]))
      
      # A tibble: 9 x 4
      # Groups:   loc.id [9]
      #   loc.id month     x all_x_less_1
      #    <int> <int> <dbl> <lgl>       
      # 1      1     8 4.46  F           
      # 2      2     7 2.25  F           
      # 3      3     8 1.18  F           
      # 4      4     5 1.13  F           
      # 5      5     1 0.758 T           
      # 6      6     5 0.715 T           
      # 7      7     5 0.639 T           
      # 8      8     2 0.509 T           
      # 9      9     1 0.395 T         
      

      诀窍是不仅要过滤x &lt; 1,还要过滤loc.id 中的所有x 是否小于1。然后使用filter 中的if_else 调用,您可以指定基于的条件关于是否所有x 都小于1。

      数据

      set.seed(123)
      df <- data.frame(loc.id = rep(1:9, each = 9), month = rep(1:9,times = 9), 
                       x = runif(81, min = 0, max = 5))
      
      df <- df %>% 
        mutate(x = x/loc.id)
      

      【讨论】:

        【解决方案3】:
        library(data.table)
        setDT(d)
        d[ , {
          ix <- x > 1 & month != 9 
          .(month = if(any(ix)) last(month[ix]) else month[which.max(x)])
        }, by = loc.id]
        

        解释:

        对于每个组 (by = loc.id),获取 x > 1 的索引,不包括第 9 个月 (x &gt; 1 &amp; month != 9)。如果任何此类索引为真 (if(any(ix))),请选择其中的最后一个月 (last(month[ix]))。否则选择对应于 max x (else month[which.max(x)]) 的月份。

        【讨论】:

          【解决方案4】:

          一个潜在的解决方案是ifelse,如果位置 8 >1.0,则位置 8,否则在排除第 9 行之后,该行的最大值。

          一个月的例子:

          month1 <- filter(df, loc.id == 1) month1 <- month1[1:8, ] df1 <- ifelse(month1[8,3] > 1.0, month1[8,3], max(month1$x))

          【讨论】:

          • 你能把这个写成解决方案吗?你会在我的剧本中把它放在哪里?谢谢
          • 由于 OP 的示例是可重现的,因此在此站点上,通常期望答案将包含适用于它的代码。
          猜你喜欢
          • 1970-01-01
          • 2021-09-01
          • 1970-01-01
          • 1970-01-01
          • 2012-06-02
          • 1970-01-01
          • 2023-03-14
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多