【问题标题】:Syntax (and/or functions) for applying an op over elements of one vector, using as arg elements of a 2nd vector用于对一个向量的元素应用运算的语法(和/或函数),使用第二个向量的 arg 元素
【发布时间】:2013-01-24 16:19:21
【问题描述】:

我试图通过对向量应用操作,以向量化的方式使用 2nd 向量的元素,来找到创建向量结果的正确表达式。用例是我有一个原始值向量和一个断点向量。我想要的是一个表达式,它将给我在断点上应用逻辑运算之和的结果,该逻辑运算相对于值向量中的值。换句话说:

给定:

rawfoo <- c(30, 4, 22, 77, 1,169, 10)
breaksfoo <- c(10,50, 80)
resultfoo <- data.frame(breaks=breaksfoo, matching=numeric(length(breaksfoo)))

我想写一个单个表达式,它为resultfoo$matching提供列值,即:对于breaksfoo中的每个值,sum(rawfoo > breaksfoo[i]),

resultfoo
  breaks nmatching
1     10         3
2     50         2
3     80         1

我一直在尝试各种形式的 apply 并且在如何表达函数方面遇到了问题。也许我在叫错树?如果需要,可以提供多个故障演示。 (但我的猜测是这个问题很简单,不需要错误消息来消除歧义;-)

【问题讨论】:

  • DWIM。那应该是 sum(rawfoo > breaksfoo[i])!
  • 您可以编辑自己的问题。

标签: r syntax apply


【解决方案1】:

您可以分三步完成:

  1. 编写一个函数,给定一个中断,返回一个包含两个元素的列表:中断本身和sum(break &gt; rawfoo) 的结果。

  2. 您可以使用sapply 将此函数应用于breaksfoo

  3. 最后,您需要转换sapply 的结果,这是一个矩阵,以获得您需要的数据帧。

以下代码在一个语句中完成所有这三个步骤:

 as.data.frame(t(sapply(breaksfoo, 
                        function(x) list(breaks = x, nmatching = sum(x > rawfoo)))))

返回

  breaks nmatching
1     10         2
2     50         5
3     80         6

【讨论】:

  • 谢谢。更正了我的 DWIM 重新评估声明!我在这里缺少的是说明要应用的操作的正确方法,以便 sapply 可以理解它。我一直在尝试声明。哪个没用。
  • 更干净的可能是:data.frame(breaks=breaksfoo,nmatching=sapply(breaksfoo,function(x) sum(x &gt; rawfoo)))
【解决方案2】:

findIntervaltable 结合使用可能会得到您想要的。

#finds which interval rawfoo is in
x <- findInterval(rawfoo,breaksfoo)
#[1] 1 0 1 2 0 3 1
#tabulates the information
table(x)
#0 1 2 3 
#2 3 1 1 
#cuts off the last element
head(table(x),-1)
#0 1 2 
#2 3 1 
resultfoo$nmatching <- head(table(x),-1)

几乎是您想要的,除了 10 被放置在第二个存储桶中,因为 findInterval 的间隔包含在下端,而您的示例将它放在第一个桶,因为你想要一个严格的不等式。您可以添加一个将重新分配给正确存储桶的校正向量:

y <- table(rawfoo)[as.character(breaksfoo)]
y[is.na(y)] <- 0
y <- y - c(0,head(y,-1))
resultfoo$nmatching <- resultfoo$nmatching + y

为了更容易做到,你可以把它包装成一个函数。

fnfoo <- function(raw,breaks) {
  x <- head(table(findInterval(rawfoo,breaksfoo)),-1)
  y <- table(rawfoo)[as.character(breaksfoo)]
  y[is.na(y)] <- 0
  x + y - c(0,head(y,-1))
}
resultfoo$nmatching <- fnfoo(rawfoo,breaksfoo)

编辑:我正在浏览另一个问题,发现cut 在这里效果更好。

data.frame(table(cut(rawfoo,c(-Inf,breaksfoo),right=TRUE)))
#        Var1 Freq
# 1 (-Inf,10]    3
# 2   (10,50]    2
# 3   (50,80]    1

【讨论】:

  • 谢谢。不知道findInterval。相信我将来会使用它。另一个答案的形式(来自 Viktor)更接近我原来的答案,所以我选择了那个。 (每次我改变一些东西并随机播放它,我都有可能破坏操作或我的注意力。)
  • 您也可以使用可选参数rightmost.closed of findInterval
  • @VictorK.:不幸的是,rightmost.closed 只适用于最右边的区间,它不会改变其他区间的封闭性。
猜你喜欢
  • 2016-12-30
  • 2019-11-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-12-25
  • 1970-01-01
  • 2012-09-06
  • 2021-05-27
相关资源
最近更新 更多