1

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

鉴于:

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 提供列值,即:对于 breakfoo 中的每个值,sum(rawfoo > breaksfoo[i]),

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

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

4

2 回答 2

2

您可以分三个步骤完成:

  1. 编写一个函数,给定一个中断,返回一个包含两个元素的列表:中断本身和sum(break > 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
于 2013-02-08T20:07:23.743 回答
1

结合可能会得到你想要的东西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
于 2013-02-08T20:18:58.957 回答