1

要約: R で gCentroid を使用すると、点群の重心が返されると思っていましたが、何らかの理由で実際には重心ではなく幾何平均が返されることに気付きました。

Rで行った重心計算を複製したかった:

gCentroid {rgeos}

これらの点の重心:

34.7573,    -86.678606  
38.30088,   -76.520266  
38.712147,  -77.158616  
39.704905,  -84.126463  

... r スクリプトを使用して ...

require(rgdal)
require(rgeos)

no_am_eq_co <- "+proj=eqdc +lat_0=0 +lon_0=0 +lat_1=20 +lat_2=60 +x_0=0 +y_0=0 +ellps=GRS80 +datum=NAD83 +units=m +no_defs"
wgs84 <- "+proj=longlat +datum=WGS84"

df <- as.data.frame(list(c(34.7573, 
                           38.30088, 
                           38.712147, 
                           39.704905),
                         c(-86.678606,
                           -76.520266,
                           -77.158616, 
                           -84.126463)))

df$Name <- "points_A"
colnames(df) <- c("lat", "lon", "Name")

# FROM: Coordinates are geographic latitude/longitudes
coordinates(df) <- c("lon", "lat")
proj4string(df) <- CRS(wgs84)

# TO: Project into North America Equidistant Conic
df <- spTransform(df, CRS(no_am_eq_co))

# Get centroids
ctrs <- lapply(unique(df$Name), 
               function(x) gCentroid(SpatialPoints(df[df$Name==x,])))
ctrsout <- setNames( ctrs , unique(df$Name ) )

# Create data frame 
df <- do.call(rbind, lapply(ctrsout, data.frame, stringsAsFactors=FALSE))
coordinates(df) <- c("x", "y")
proj4string(df) <- CRS(no_am_eq_co) 
df <- as.data.frame(spTransform(df, CRS(wgs84)))
names(df) <- c("longitude", "latitude")

print(df$latitude)
print(df$longitude)  

に来た:

37.94873834, -81.18378815

私はPythonで次の例を作成しました-次を使用して計算を複製したかったのです:

ここに画像の説明を入力

ここに画像の説明を入力

ここに画像の説明を入力

import numpy as np
from pyproj import Proj, transform

# Using: http://www.spatialreference.org/ref/esri/102010/ we get the Proj4js format
na_eq_co = "+proj=eqdc +lat_0=0 +lon_0=0 +lat_1=20 +lat_2=60 +x_0=0 +y_0=0 +ellps=GRS80 +datum=NAD83 +units=m +no_defs"
wgs84 = "+proj=longlat +datum=WGS84"

def proj_arr(points,proj_from,proj_to):
    inproj = Proj(proj_from)
    outproj = Proj(proj_to)
    func = lambda x: transform(inproj,outproj,x[0],x[1])
    return np.array(list(map(func, points)))

def get_polygon_centroid(polygon):
    #https://en.wikipedia.org/wiki/Centroid#Centroid_of_polygon
    pol = np.array(polygon)
    if np.any(pol[-1] != pol[0]):
        pol = np.append(pol,[pol[0]], axis=0)
    pol_area = get_polygon_area(pol)
    x = pol[:,0]
    y = pol[:,1]
    Cx = np.sum((x[:-1] + x[1:]) * ((x[:-1] * y[1:]) - (y[:-1] * x[1:]))) / (6. * pol_area)
    Cy = np.sum((y[:-1] + y[1:]) * ((x[:-1] * y[1:]) - (y[:-1] * x[1:]))) / (6. * pol_area)
    return np.array([Cx, Cy])

def get_polygon_area(polygon):
    pol = np.array(polygon)
    x = pol[:,0]
    y = pol[:,1]
    return np.sum( (x[:-1] * y[1:]) - (y[:-1] * x[1:]) ) / 2 

def get_polygon_mean(polygon):
    pol = np.array(polygon)
    x = pol[:,0]
    y = pol[:,1]
    return np.array([np.mean(x),np.mean(y)])

def run_test(points):
    points = points[:,::-1] #Flip-axis (so that longitude x-axis, latitude y-axis)
    points_proj = proj_arr(points,wgs84,na_eq_co)

    centroid_proj = get_polygon_centroid(points_proj)
    mean_proj = get_polygon_mean(points_proj)

    centroid = proj_arr([centroid_proj],na_eq_co,wgs84)
    mean = proj_arr([mean_proj],na_eq_co,wgs84)
    return (centroid[:,::-1][0], mean[:,::-1][0])

if __name__ == '__main__':
    my_points = np.array([[34.7573,-86.678606],
                       [38.30088,-76.520266],
                       [38.712147,-77.158616],
                       [39.704905,-84.126463]])

    test = run_test(my_points)
    print("Centroid calculation: {0}\nMean calculation {1}".format(test[0],test[1]))

これから私は得る:

37.72876321 -82.35113685  

いいえ:

37.94873834,-81.18378815 

もう少し掘り下げて、幾何平均を与える関数を追加しました。

Centroid calculation: [ 37.72876321 -82.35113685]
Mean calculation [ 37.94873834 -81.18378815]

何らかの理由で、gCentroid が特徴の重心ではなく幾何平均を計算しているように見えることに気付きました (R の結果と一致することがわかる平均関数を追加しました)

編集:

おそらくその理由は次のとおりだと思いました。ポイントのグループ化があったため、ランダムなポリゴンをそれらに通して(例の私のように)、または凸包をフィッティングしてからその重心を取得する代わりに、コマンドはデフォルトでデータ型が「ポイント」の場合の平均計算。だから私は明示的にポリゴンを渡しました:

x = readWKT(paste("POLYGON((-6424797.94257892  7164920.56353916,
                  -5582828.69570672  6739129.64644454,
                  -5583459.32266293  6808624.95123077,
                  -5855637.16642608  7316808.01148585,
                  -5941009.53089084  7067939.71641507,
                  -6424797.94257892  7164920.56353916))"))

python_cent = readWKT(paste("POINT(-5941009.53089084  7067939.71641507)"))
r_cent = gCentroid(x) 

plot(x)
plot(r_cent,add=T,col='red')
plot(python_cent, add=T,col='green')

Python 重心は次のとおりです。

centroid = get_polygon_centroid(np.array([[-6424797.94257892,  7164920.56353916],
                                             [-5582828.69570672,  6739129.64644454],
                                             [-5583459.32266293,  6808624.95123077],
                                             [-5855637.16642608, 7316808.01148585],
                                             [-6424797.94257892, 7164920.56353916]]))

次に、これの重心を赤 ( -5875318 7010915 ) でプロットし、同じポリゴン (python を使用) の重心を緑 ( -5941009 7067939 ) でプロットし、単純平均 ( -5974304 7038880 ) を青でプロットします。

ここに画像の説明を入力

4

1 に答える 1

1

'点' のグループが指定された場合、点から多角形を推測したり、凸包を生成したりする代わりに、コマンドは投影された座標の平均を自動的に返します。

ただし、ポリゴンを指定すると、セントロイドが得られます (python スクリプトと同じ)。私の python の例では、座標が 1 つ欠けていました。

centroid = get_polygon_centroid(np.array([[-6424797.94257892,  7164920.56353916],
                                             [-5582828.69570672,  6739129.64644454],
                                             [-5583459.32266293,  6808624.95123077],
                                             [-5855637.16642608, 7316808.01148585],
                                             [-5941009.53089084,  7067939.71641507],
                                             [-6424797.94257892, 7164920.56353916]]))
#polygon closed
#[-5875317.84402261  7010915.37286505]

したがって、この R スクリプトを実行すると、次のようになります。

x = readWKT(paste("POLYGON((-6424797.94257892  7164920.56353916,
                  -5582828.69570672  6739129.64644454,
                  -5583459.32266293  6808624.95123077,
                  -5855637.16642608  7316808.01148585,
                  -5941009.53089084  7067939.71641507,
                  -6424797.94257892  7164920.56353916))"))

python_cent = readWKT(paste("POINT(-5875317.84402261  7010915.37286505)"))
r_cent = gCentroid(x) 

plot(x)
plot(r_cent,add=T,col='red', pch = 0)
plot(python_cent, add=T,col='green', pch = 1)

すべてがうまく一致します:

ここに画像の説明を入力

興味があれば、ブログにもう少し情報を追加しました。

于 2016-03-02T15:55:07.027 に答える