如何计算R中“n”维范围内的观测数

时间:2017-10-20 13:03:45

标签: r dataframe count apply

我创建了一个点的2D地图

set.seed(3000)
Citysize <-1000
Range <- 0.05
vertical<-rnorm(Citysize,0,1)
horizontal<-rnorm(Citysize,0,1)
Map <-as.data.frame(cbind(vertical,horizontal))
plot(Map)

其中一些点是特殊的

special <- runif(Citysize,0,1)
Map <-as.data.frame(cbind(vertical,horizontal,special))
Map$special[Map$special >0.8] <- 1
Map$special[Map$special <0.8] <- 0

每个点都是一个正方形的中心,我想知道这个正方形内有多少个点。

Map$v1 <- Map$vertical - Range 
Map$v2 <- Map$vertical + Range
Map$h1 <- Map$horizontal - Range 
Map$h2 <- Map$horizontal + Range 

我试过了

apply(Map, 1, function(x) length(which(x[1]>Map[4]& x[1]<Map[5])))

仅适用于1个条件(垂直),但我不知道如何包含其他条件。有什么建议吗?

2 个答案:

答案 0 :(得分:0)

您可以使用verticalhorizontal介于v1/v2h1/h2之间的条件将数据加入到自身中。在这种情况下,我使用data.table,但您可以使用任何支持非equi连接的其他内容(如sqldf)。从我对你的问题的理解,我忽略了&#34;特殊的点&#34;因为您提供的示例代码似乎没有考虑到它们。

res <- setDT(Map)[Map, .(i.vertical, i.horizontal, i.v1, i.v2, i.h1, i.h2, x.vertical, x.horizontal), 
                        on=.( vertical >= v1, vertical <= v2, horizontal >= h1, horizontal <= h2)]

res2 <- res[, .(count = .N - 1), by = .(i.vertical, i.horizontal, i.v1, i.v2, i.h1, i.h2)]

head(res2)
#   i.vertical i.horizontal       i.v1       i.v2       i.h1       i.h2 count
#1:  1.2582925    0.5991733  1.2082925  1.3082925  0.5491733  0.6491733     1
#2:  0.6447519   -0.9258515  0.5947519  0.6947519 -0.9758515 -0.8758515     2
#3:  0.4633460   -2.0512540  0.4133460  0.5133460 -2.1012540 -2.0012540     0
#4:  0.7703058    0.2609452  0.7203058  0.8203058  0.2109452  0.3109452     0
#5: -0.2263347   -0.7152786 -0.2763347 -0.1763347 -0.7652786 -0.6652786     0
#6: -0.3515479    0.4835811 -0.4015479 -0.3015479  0.4335811  0.5335811     0

注意我从组的长度中减去了一个因为它与自身的观察匹配所以我们需要排除它。

答案 1 :(得分:0)

在我看来,这个解决方案很丑陋,可能会做得更好,但至少它会遵循你的语法。我将Map$special更改为逻辑向量,并在&#34;之间使用了%b%&#34;功能,因为我觉得它很容易阅读。

## is lhs between (strict) rhs? (Vectorized)
`%b%` <- function(x,rng) min(rng) < x & x < max(rng)

## Horizontal and vertical values of special points
specialh <- Map$horizontal[Map$special]
specialv <- Map$vertical[Map$special]

## For each special point check if Map point is in range
sapply(1:length(specialh), function(i){
    h <- Map$horizontal %b% c(specialh[i] + Range * c(-1,1))
    v <- Map$vertical %b% c(specialv[i] + Range * c(-1,1))

    ## Subtract 1 because otherwise we count the point itself
    sum(h&v) - 1
})

#   [1] 0 2 0 0 3 0 0 0 0 1 0 2 1 0 0 3 0 0 2 0 0 2 1 1 2 0 0
#  [28] 1 0 0 1 1 0 0 1 0 3 1 1 1 0 0 2 1 1 4 1 0 0 1 0 0 0 3
#  [55] 0 0 0 1 1 0 2 2 0 2 0 1 2 0 0 0 0 2 1 0 1 0 0 1 0 3 1
#  [82] 0 1 0 1 2 2 0 2 1 0 0 1 0 0 0 0 0 3 2 2 1 1 0 0 0 0 0
# [109] 0 0 2 0 0 0 2 0 0 1 0 1 0 1 1 2 1 3 0 0 0 0 0 1 0 0 2
# [136] 1 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 2 0 0 3 0 0 0 1 0 0 0
# [163] 0 0 2 0 2 0 0 2 0 0 0 1 1 0 0 0 2 0 1 3 1 0 0 0 3 0 0
# [190] 0 3 0 0 0 0 1 2