0

给定一个带有 x*y 单元格的网格(或表格)。每个单元格包含一个值。大多数这些单元格的值为 0,但在该网格的某处可能存在一个“热点”,其中一个单元格具有较高的值。该单元格的相邻单元格的值也 > 0。离热点越远,相应网格单元格中的值越低。

所以这个热点可以看作是山顶,离这座山越远,数值越小。在一定距离处,值再次下降到 0。

现在我需要确定网格中代表网格重心的单元格。在上面的简单示例中,该质心将只是具有最高值的一个单元格。然而,事情并不总是那么简单:

  1. 热点小区周围相邻小区的递减值可能不是均匀分布的,或者“山的一侧”可能比另一侧更早地下降到 0。

  2. 网格内还有另一个热点/山,其值 > 0。

我可以认为这是一个典型的问题。不幸的是,我不是数学专家,所以我不知道要搜索什么(至少我还没有在 Google 中找到答案)。

有什么想法可以解决这个问题吗?

提前致谢。

4

2 回答 2

3

您正在寻找单元格值的“加权平均值”。假设每个单元格都有一个值 z(x,y),那么您可以执行以下操作

zx = sum( z(x, y) ) over all values of y
zy = sum( z(x, y) ) over all values of x

meanX = sum( x * zx(x)) / sum ( zx(x) )
meanY = sum( y * zy(y)) / sum ( zy(y) )

我相信您可以将其转换为您选择的语言...

例子:如果你知道Matlab,那么上面的写法如下

zx = sum( Z, 1 ); % sum all the rows
zy = sum( Z, 2 ); % sum all the columns

[ny nx] = size(Z); % find out the dimensions of Z

meanX = sum((1:nx).*zx) / sum(zx);
meanY = sum((1:ny).*zy) / sum(zy);

这将为您提供 1 .. nx 范围内的 meanX:如果它在中间,则值为 (nx+1)/2。您显然可以根据自己的需要进行扩展。

编辑:再一次,在“几乎真实”的代码中:

// array Z(N, M) contains values on an evenly spaced grid
// assume base 1 arrays

zx = zeros(N);
zy = zeros(M);

// create X profile:
for jj = 1 to M
  for ii = 1 to N
    zx(jj) = zx(jj) + Z(ii, jj);
  next ii
next jj

// create Y profile:
for ii = 1 to N
  for jj = 1 to M
    zy(ii) = zy(ii) + Z(ii, jj);
  next jj
next ii

xsum = 0;
zxsum = 0;
for ii = 1 to N
  zxsum += zx(ii);
  xsum += ii * zx(ii);
next ii
xmean = xsum / zxsum;

ysum = 0;
zysum = 0;
for jj = 1 to M
  zysum += zy(jj);
  ysum += jj * zy(ii);
next jj
ymean = ysum / zysum;
于 2013-02-02T03:46:20.120 回答
1

这个维基百科条目可能会有所帮助;标题为“粒子系统”的部分就是您所需要的。只需了解您需要为每个维度进行一次计算,显然您有两个。

这是一个完整的 Scala 2.10 程序,用于生成一个充满随机整数的网格(使用命令行上指定的尺寸)并找到重心(其中行和列从 1 开始编号):

object Ctr extends App {
  val Array( nRows, nCols ) = args map (_.toInt)
  val grid = Array.fill( nRows, nCols )( util.Random.nextInt(10) )
  grid foreach ( row => println( row mkString "," ) )
  val sum = grid.map(_.sum).sum
  val xCtr = ( ( for ( i <- 0 until nRows; j <- 0 until nCols )
    yield (j+1) * grid(i)(j) ).sum :Float ) / sum
  val yCtr = ( ( for ( i <- 0 until nRows; j <- 0 until nCols )
    yield (i+1) * grid(i)(j) ).sum :Float ) / sum
  println( s"Center is ( $xCtr, $yCtr )" )
}

你可以定义一个函数来保持计算 DRYer,但我想让它尽可能明显。无论如何,我们在这里运行它几次:

$ scala Ctr 3 3
4,1,9
3,5,1
9,5,0
Center is ( 1.8378378, 2.0 )

$ scala Ctr 6 9
5,1,1,0,0,4,5,4,6
9,1,0,7,2,7,5,6,7
1,2,6,6,1,8,2,4,6
1,3,9,8,2,9,3,6,7
0,7,1,7,6,6,2,6,1
3,9,6,4,3,2,5,7,1
Center is ( 5.2956524, 3.626087 )
于 2013-02-02T04:46:41.667 回答