R:基于以不同数据集中的点为中心的某种分布从数据集中进行采样

时间:2018-07-23 19:35:48

标签: r sampling

我试图根据点在X-Y平面上的分布,在X-Y-Z空间中从一组点df_map中采样行。分布的平均值和标准偏差在另一个数据集中df_pts中。

我的数据看起来像这样

> df_map
   X  Y   Z
A  6  0 103
B -4  2 102
C -2 15 112
D 13  6 105
E  1 -3 117
F  5 16 105
G 10  5 103
H 14 -7 119
I  8 14 107
J -8 -4 100

> df_pts
    x   y   accuracy
a   5  18 -0.8464018
b   3   2  0.5695678
c -18  14 -0.4711559
d  11  13 -0.7306417
e  -3 -10  2.1887011
f  -9 -11  2.1523923
g   5   1 -0.9612284
h  12 -19 -0.4750582
i -16  20 -1.4554292
j   0  -8  3.4028887

我要遍历df_pts中的行,并根据距(df_pts[i, x], df_pts[i, y])的距离的高斯分布以2d标准偏差为df_pts[i, accuracy]从df_map中选择一行。换句话说,在每个i = 1:10,我想根据均值df_pts[i, x]^2 + df_pts[i, y]^2和2d sd df_pts[i, accuracy]的正态分布从df_map中取样。

对于有效且复杂的方法,我将不胜感激。我是R的新手,来自C的背景,我这样编码任务的方式涉及使用基本操作的每一步太多的基础循环和计算,这使代码非常慢。

如果问题过于琐碎或框架不够明确,我谨向您道歉。

2 个答案:

答案 0 :(得分:1)

易于使用的数据:

df_map <- data.frame(x = c(6,-4,-2,13,1,5,10,14,8,-8),
                     y= c(0,2,15,6,-3,16,5,-7,14,-4),
                     z= c(103,102,112,105,117,105,103,119,107,100))
df_pts <- data.frame(x = c(5,3,-18,11,-3,-9,5,12,-16,0),
              y= c(18,2,14,13,-10,-11,1,-19,20,-8),
              accuracy = c(-0.8464018, 0.5695678,-0.4711559,-0.7306417, 2.1887011, 2.1523923,-0.9612284,-0.4750582,-1.4554292,3.4028887))

我认为您正在寻找的是最近的邻居搜索。过去我为此付出了很多努力,但这是我想出的代码:

library("FNN")

findNeighbour <- function(index){
  first = df_pts[index,1:2]
  hit = get.knnx(df_map[c("x","y")], first, k =1 )
  hit_index = hit[[1]]
  hit_result = df_map[hit_index,]
  result = append(df_pts[index,], hit_result)
}
t <- do.call(rbind, lapply(1:nrow(df_map),findNeighbour))

结果为:

     x   y   accuracy x.1 y.1   z
1    5  18 -0.8464018   5  16 105
2    3   2  0.5695678   6   0 103
3  -18  14 -0.4711559  -2  15 112
4   11  13 -0.7306417   8  14 107
5   -3 -10  2.1887011  -8  -4 100
6   -9 -11  2.1523923  -8  -4 100
7    5   1 -0.9612284   6   0 103
8   12 -19 -0.4750582  14  -7 119
9  -16  20 -1.4554292  -2  15 112
10   0  -8  3.4028887   1  -3 117

在此示例中,您可以看到多次匹配了一些数据,因此,根据您的目标,您可能希望将这些数据排除在外或进行双向搜索。

我希望这就是您要寻找的

答案 1 :(得分:0)

谢谢你的建议。

我最终做了以下事情

df_map <- data.frame(X = c(6,-4,-2,13,1,5,10,14,8,-8),
                     Y= c(0,2,15,6,-3,16,5,-7,14,-4),
                     Z= c(103,102,112,105,117,105,103,119,107,100))
df_pts <- data.frame(x = c(5,3,-18,11,-3,-9,5,12,-16,0),
                     y= c(18,2,14,13,-10,-11,1,-19,20,-8),
                     accuracy = c(-0.8464018, 0.5695678,-0.4711559,-0.7306417, 2.1887011, 2.1523923,-0.9612284,-0.4750582,-1.4554292,3.4028887))

map.point2map <- function(map_in, pt_in) {
  dists <- dist(rbind(cbind(x = pt_in['x'],
                           y = pt_in['y']),
                     cbind(x = map_in$X,
                           y = map_in$Y)))[1:dim(map_in)[1]]

  mu <- mean(dists)
  stddev <- abs(as.numeric(pt_in['accuracy']))

  return(sample_n(tbl = map_in[, c('X', 'Y')],
                  size = 1,
                  replace = TRUE,
                  weight = dnorm(dists, mean = mu, sd = stddev)))
}

mapped <- apply(df_pts,
                1,
                function(x) map.point2map(map_in = df_map,
                                          pt_in = x))

并根据需要映射了从df_map采样的10个点的列表。