【问题标题】:rewrite a base R function with dplyr - utilizing filter instead of []用 dplyr 重写基本 R 函数 - 使用过滤器而不是 []
【发布时间】:2018-10-29 14:41:29
【问题描述】:
makeparts <- function(x, n) {
  x <- unique(c(0, x))
  x <- x[x >= 0 & x < n]
  x <- x[order(x)]
  x <- rep(c(seq_along(x)), diff(c(x, n)))
  x
}

makeparts(c(20, 30, 58), 100)

如何使用 dplyr 重写这个函数?我在 tidyverse 中相当出色,但从未学习过 base R。我什至不知道上面的那个函数在做什么。如果我在 tidyverse 语法中看到它,我可以理解该函数(可能)。这是我的最终目标。

所有的 tidyverse 动词都有意义,但这个 [, x] [[df]] 东西没有。

【问题讨论】:

  • filter 用于数据帧,您最好了解基本 R 函数,dplyrtidyverse 包的作用是补充基本函数,而不是替换它们,尽管它确实用近似的等效函数替换了一些函数。
  • @Moody_Mudskipper 渴望学习基础 R ,在 Vim、SQL、LaTeX、Linux 命令行等之上。但是很好的建议,尤其是对其他人。谢谢。
  • 我知道这可能会让人不知所措,但请相信我,理解 [[[R 的首选,无论是否整洁。
  • 一个更广泛的建议:如果您不了解该函数,请通过一次添加一行来重建它,运行它,然后看看会发生什么

标签: r function dplyr


【解决方案1】:

这是一个重新格式化的版本,使用更类似于 tidyverse 的代码:

x %>% 
  unique %>%
  keep(~.>=0 & .<n) %>%
  sort %>%
  c(0,.,n) %>%
  diff %>%
  list(lengths = ., values = seq_along(.)) %>%
  inverse.rle

# [1] 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2
# [31] 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 4 4
# [61] 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4
# [91] 4 4 4 4 4 4 4 4 4 4

【讨论】:

    【解决方案2】:

    x 看起来像是一个向量。第一步使用unique,与tidyverse 中的distinct 相同。下一行使用[ 运算符,用于索引向量或矩阵。 [ ] 内部的值应该(出于所有意图和目的)评估为 TRUEFALSE 值或数字的向量。这与 tidyverse 中的 filter 相同。下一行在x 上使用order,与arrange 相同。最后一步做了两件事:1)它重复来自seq_along(x)的值,在这个例子中,它们是1、2、3和4。然后它将xn连接在一起,得到@ 987654335@ 然后在它们上运行diff,它将取第二个元素并减去第一个元素,取第三个元素并减去第二个元素,等等。这给了我们c(20, 10, 28, 42),因为 (20-0) = 20, (30 -20) = 10,以此类推。最后一步是使用 lag 函数在 tidyverse 中可以实现的。 rep 函数没有直接的 tidyverse 等效项。正如上面的 cmets 中提到的,这不能转换为 tidyverse 函数,因为这些函数用于数据帧并且您有一个向量。我同意你应该学习基础 R。你只能用 tidyverse 走这么远。

    更新:

    按要求添加此代码的 tidyverse 版本。

    makeparts <- function(x, n) {
        x <- unique(c(0, x))
        x <- x[x >= 0 & x < n]
        x <- x[order(x)]
        x <- rep(c(seq_along(x)), diff(c(x, n)))
        x
    }
    
    makeparts_tidyverse <- function(x, n) {
        df = data_frame(x = c(0, x)) %>%
            distinct() %>%
            filter(x >= 0 & x < n) %>%
            arrange(x) %>%
            bind_rows(data_frame(x = n)) %>%
            mutate(lag_x = lag(x)) %>%
            mutate(y = x - lag_x) %>%
            filter(!is.na(y))
        rep(seq_along(df$x), df$y)
    }
    
    > makeparts(c(20, 30, 58), 100)
      [1] 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
     [21] 2 2 2 2 2 2 2 2 2 2 3 3 3 3 3 3 3 3 3 3
     [41] 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 4 4
     [61] 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4
     [81] 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4
    
    > makeparts_tidyverse(c(20, 30, 58), 100)
      [1] 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
     [21] 2 2 2 2 2 2 2 2 2 2 3 3 3 3 3 3 3 3 3 3
     [41] 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 4 4
     [61] 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4
     [81] 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4
    

    【讨论】:

    • 感谢您提供这个解释清楚的答案。你能不能逗我一下,用最接近tidyverse 语法的方式写makeparts?我非常渴望学习base-R和will。只是我还需要学习 Vim、LaTeX、SQL 和很多东西啊啊啊啊!!! :) 但我喜欢它。与此同时,tidyverse 非常强大,也非常易于使用。
    • 欢迎来到数据分析的世界,哈哈!陡峭的学习曲线,但当所有这些结合在一起时,它是如此令人满意。让我尽我所能把它变成一个 tidyverse 的东西。
    猜你喜欢
    • 2023-03-12
    • 1970-01-01
    • 1970-01-01
    • 2021-11-30
    • 1970-01-01
    • 2016-08-04
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多