【问题标题】:Elegant way to vectorize seq?向量化 seq 的优雅方式?
【发布时间】:2013-04-01 18:51:36
【问题描述】:

尽管标题相似,但这与Vectorizing rep and seq in R 不是同一个问题。

我的直接目标:给定一个向量,我想生成一个新向量,其中包含原始值以及旧值中每个值之间的规则间隔。这并不难。

一种策略是使用更通用的函数,给定两个向量和指定的by 区间,使用相同的by 值重复将 seq 应用于两个原始向量中的数字对。我还没有找到执行此操作的内置函数。 seq 似乎拒绝将向量作为参数处理。这是一个执行更一般操作的函数(然后我可以立即使用它):

multiseq <- function(froms, tos, by){
  x <- c(); 
  for (i in seq_along(froms)){
    x <- c(x, seq(from=froms[i], to=tos[i], by=by))
  }
  x
}

例如:

> multiseq(1:2, 1.75:2.75, .25)
[1] 1.00 1.25 1.50 1.75 2.00 2.25 2.50 2.75

(这只是一个简单的例子。我真正想要的是用任意序列来做这个,例如

-0.89115386 -0.75346155 -0.61576924 -0.47807693 -0.34038463 -0.20269232 -0.06500001  0.07269230  0.21038460  0.34807691  0.48576922  0.62346153  0.76115383

我想将每个间隔细分为五个,以创建一个包含 5 倍多的元素的新序列。)

只要序列不太长,我相信重复扩展向量不应该太慢。如果我需要大序列,我可以重写以预先扩展向量并填充它。然而,我仍然用循环来做这件事。有没有更优雅的函数式编程 R-ly 方式?

谢谢。

【问题讨论】:

  • 我没有得到你想要的 seq(1, 2.75, by=.25) 做同样的事情吗?
  • 谢谢@TylerRinker。我已经编辑澄清。嗯,但现在我想,你是对的。我只是没有正确地考虑它。对于新示例,我可以使用seq(-0.89115386, 0.76115383, 0.1376923/5)。我也意识到我可以使用c(mapply(seq, firstseq, secondseq, MoreArgs=list(by=0.1376923/5))。不确定是撤回问题还是回答。
  • 回答它并接受您的回答,这是完全有效的(尽管您必须等待几天才能接受它)。我正要提出同样的建议。 multiseq &lt;- function(froms, tos, ...) as.vector(mapply(seq, froms, tos, ...)),然后做multiseq(froms, tos, by=0.1)(比如说)。

标签: r


【解决方案1】:

在 R 中,对函数进行矢量化的最简单方法之一是使用 Vectorize 函数。

基本上,您可以将fromto 参数向量化,并将所有启动器作为from 参数中的向量,并对to 参数执行相同的操作。

使用你的例子,你可以做这样的事情

seq2 <- Vectorize(seq.default, vectorize.args = c("from", "to"))

unlist(seq2(from = c(1, 1.75), to = c(2, 2.75), by = 0.25))

## [1] 1.00 1.25 1.50 1.75 2.00 1.75 2.00 2.25 2.50 2.75

【讨论】:

  • + 1 并删除我写一半的回复。您应该将其发布为原始问题中链接的not duplicate 的答案。
  • @mnel,也许它也应该在那里发布,但这个问题比标题所暗示的要具体得多。
  • 谢谢 dickoa。我曾尝试将Vectorizeseq 一起使用,这会产生错误。 seq.default 是什么?此类功能存在时的一般规则是什么,它们是什么?一个好的来源(甚至是适当的搜索字符串)的指针将不胜感激。
【解决方案2】:

尝试关注

x <- c(1, 2, 4, 8)
y <- unlist(mapply(FUN = function(from, to) {
    seq(from = from, to = to, by = 0.25)
}, head(x, -1), tail(x, -1)))
y
##  [1] 1.00 1.25 1.50 1.75 2.00 2.00 2.25 2.50 2.75 3.00 3.25 3.50 3.75 4.00 4.00 4.25 4.50 4.75 5.00 5.25 5.50 5.75 6.00
## [24] 6.25 6.50 6.75 7.00 7.25 7.50 7.75 8.00

result <- y[!duplicated(y)]
result
##  [1] 1.00 1.25 1.50 1.75 2.00 2.25 2.50 2.75 3.00 3.25 3.50 3.75 4.00 4.25 4.50 4.75 5.00 5.25 5.50 5.75 6.00 6.25 6.50
## [24] 6.75 7.00 7.25 7.50 7.75 8.00

【讨论】:

    【解决方案3】:

    正如@TylerRinker 在对我的问题的评论中所建议的那样,对于我的特殊需求,有一个比我对问题的表述所建议的更简单的解决方案——我太专注于一种特定的思考方式。由于我希望在已经规则间隔的数字之间插值规则间隔的数字,因此我可以将seq 应用于向量中的初始值和最终值,使用by 值均匀划分为原始值之间的间隔向量:

    subdiv <- function(x, by) seq(x[1], x[length(x)], by)
    subdiv(1:4, .25)
    [1] 1.00 1.25 1.50 1.75 2.00 2.25 2.50 2.75 3.00 3.25 3.50 3.75 4.00
    subdiv(c(-0.20269232, -0.06500001,  0.07269230), 0.1376923/3)
    [1] -0.20269232 -0.15679489 -0.11089745 -0.06500002 -0.01910259  0.02679485  0.07269228
    

    其中 0.1376923 是第二个应用程序中连续元素之间的差异。只要我不需要从原始向量中携带的元素完全等于它们的原始值,这个解决方案就可以了——正如您所看到的,由于浮点运算存在一些差异。 (我实际上在做的是为直方图构建 bin;精确的边界并不重要。)

    @dickoa 和 @geektrader 的答案有更广泛的用途,但可以保留输入向量中原始数字的确切值。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-03-07
      • 2012-07-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-06-19
      • 2014-09-01
      相关资源
      最近更新 更多