代码之家  ›  专栏  ›  技术社区  ›  Sean

创建列,在其他列中给出下一个相等或更小的值

  •  0
  • Sean  · 技术社区  · 5 月前

    我想创建一个列 col2 其中列出了中每个元素的行距离 col1 到中的下一个值 col1 其等于或低于。

    当没有更多相等或更低的元素时,它给出了到柱末端的距离。

    数据帧示例:

    df1 <- data.frame(col1 = c(1,2,2,1,2,3,2))
    
      col1
    1    1
    2    2
    3    2
    4    1
    5    2
    6    3
    7    2
    

    本例中的期望输出:

      col1 col2
    1    1    3
    2    2    1
    3    2    1
    4    1    4
    5    2    3
    6    3    1
    7    2    1
    

    到目前为止,我的尝试如下。虽然当我尝试使用向量时,这似乎有效,但它在函数中不起作用。

    这是为了输入到我试图编写的更广泛的函数中。

    df1 |>
      mutate(
          col2 = sapply(row_number(), \(x) {
          distance <- match(TRUE, col1[x] <= col1[(x+1):n()]) 
          distance
        })
      )
    
    2 回复  |  直到 5 月前
        1
  •  1
  •   Tim G    5 月前

    当前方法的主要问题是处理没有更低/相等值的情况——在这些情况下,我们需要到数据帧末尾的距离。你的前4应该是3,因为需要3行才能再次等于或小于1。

    df1 |>
      mutate(
        col2 = sapply(seq_len(n()), \(x) {
          matches <- which(col1[-(1:x)] <= col1[x])
          if (length(matches)) matches[1] else n() - x + 1
        })
      )
    
    col1 col2
    1. 3.
    2. 1.
    2. 1.
    1. 4.
    2. 2.
    3. 1.
    2. 1.
        2
  •  1
  •   Jon Spring    5 月前

    我的方法是首先将行号作为显式行添加,因为您是在计算这些行号。然后,我进行滚动自连接,找到小于或等于当前行的下一行 col1 然后,我取行差或剩余行数之间的第一个NA。

    library(dplyr)
    df2 <- df1 |> mutate(row = row_number())
    df2 |>
      left_join(df2, join_by(closest(row < row), col1 >= col1)) |>
      transmute(col1 = col1.x, col2 = coalesce(row.y - row.x, n() - row.x + 1))
    

    结果

      col1 col2
    1    1    3
    2    2    1
    3    2    1
    4    1    4
    5    2    2
    6    3    1
    7    2    1