【问题标题】:Match value in column within a range of another column on the same dataframe and return corresponding row匹配同一数据帧上另一列范围内的列中的值并返回相应的行
【发布时间】:2021-09-28 18:51:34
【问题描述】:

我正在尝试找到最佳方法来获取位于 Z 列范围内的 Y 列的值并返回相应的行。

例如,考虑 X 列中的 A,Y 中的值为 25,因此它介于 20 和 30 之间,因此 W 中的对应值为 2。

## example dataframe
df <- data.frame(X=c("A","A","A","A","B","B","B","C","C","C"),
                 Y=c(25,25,25,25,35,35,35,15,15,15),
                 Z=c(10,20,30,40,10,20,30,10,20,30),
                 w=c(1,2,3,4,1,2,3,1,2,3))

#desired dataframe
df2 <- data.frame(X=c("A","B","C"),
                  Y=c(25,35,15),
                  Z=c(20,30,10),
                  w=c(2,3,1)) 

问题需要解决。假设 D 的值 Y (5) 小于 min Z (10) 在这种情况下它会得到 0。如何实现?

df <- data.frame(X=c("A","A","A","A","B","B","B","C","C","C","D","D","D"),
                 Y=c(25,25,25,25,35,35,35,15,15,15,5,5,5),
                 Z=c(10,20,30,40,10,20,30,10,20,30,10,20,30),
                 w=c(1,2,3,4,1,2,3,1,2,3,1,2,3))

df2 <- data.frame(X=c("A","B","C","D"),
                  Y=c(25,35,15,5),
                  Z=c(20,30,10,0),
                  w=c(2,3,1,0)) 

【问题讨论】:

    标签: r tidyverse


    【解决方案1】:

    有几种方法可以做到这一点(取决于逻辑)。一种方法是按“X”分组,得到在“Z”和“Y”之间具有minimum absolute 差异的行。请注意,对于“X”中的“B”元素,选择的行是我们不知道 Y 是否在范围内的最后一行

    library(dplyr)
    df %>%
        group_by(X) %>%
        slice(which.min(abs(Z - Y))) %>%
        ungroup
    

    -输出

    # A tibble: 3 × 4
      X         Y     Z     w
      <chr> <dbl> <dbl> <dbl>
    1 A        25    20     2
    2 B        35    30     3
    3 C        15    10     1
    

    或者另一种选择是在按“X”分组后创建一个lead 列,在filter 中创建一个逻辑向量并使用if/else 返回没有上限的情况,即“B”

    df %>% 
       group_by(X) %>%
       mutate(Z1 = lead(Z, default = last(Z))) %>% 
       filter({tmp <- Y > Z & Y <Z1
         if(any(tmp)) tmp else row_number() == n()
        }) %>%
        ungroup %>% 
        select(-Z1)
    

    【讨论】:

    • 谢谢阿克伦。第二个解决方案解决了这个问题。
    【解决方案2】:

    也许我们可以试试下面的data.table

    > setDT(df)[, .SD[findInterval(Y, Z) == seq_along(w)], X]
       X  Y  Z w
    1: A 25 20 2
    2: B 35 30 3
    3: C 15 10 1
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2019-05-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-06-25
      相关资源
      最近更新 更多