2

私のデータベースには次の構造があります。

    > long <- c(13.2345, 14.2478, 16.2001, 11.2489, 17.4784, 27.6478, 14.2500, 12.2100, 11.2014, 12.2147)
    > lat <- c(47.1247, 48.2013, 41.2547, 41.2147, 40.3247, 46.4147, 42.4786, 41.2478, 48.2147, 47.2157)
    > hh_id <- 1:10
    > vill_id <- c(rep(100, 4), rep(101, 3), rep(102, 2), 103)

    > df <- matrix(c(long, lat, hh_id, vill_id), nrow = 10, ncol = 4)
    > colnames(df) <- c("longitude", "latitude", "hh_id", "vill_id") 
    > df <- as.data.frame(df)
    > df
       longitude latitude hh_id vill_id
       13.2345  47.1247     1     100
       14.2478  48.2013     2     100
       16.2001  41.2547     3     100
       11.2489  41.2147     4     100
       17.4784  40.3247     5     101
       27.6478  46.4147     6     101
       14.2500  42.4786     7     101
       12.2100  41.2478     8     102
       11.2014  48.2147     9     102
       12.2147  47.2157    10     103

hh_id - 世帯 ID

vill_id - 村の ID

同じ ID を持つ世帯は同じ村に属します。

私の目的: 同じ vill_id を持つすべてのポイント間の平均距離を計算し、結果を新しいデータ フレームに保存します。

vill_id    mean_dist
100        587553.5
101        …………………
102        …………………
103        ………………

私のアプローチ: ポイント間の測地距離を計算するために、geosphere パッケージの distm コマンドを使用しました (distVincentyEllipsoid が最も正確なはずです)。

> library(geosphere)
> df_100 <- df[df$vill_id == 100, ]
> dist_100 <- distm(df_100, fun = distVincentyEllipsoid)
Error in .pointsToMatrix(p1) : Wrong length for a vector, should be 2 --> 
> df_100_2 <- df_100[, c(1, 2)]
> dist_100_2 <- distm(df_100_2, fun = distVincentyEllipsoid)
> dist_100_2
         [,1]     [,2]     [,3]     [,4]
[1,]      0.0 141844.7 693867.8 675556.9
[2,] 141844.7      0.0 787217.4 811777.4
[3,] 693867.8 787217.4      0.0 415056.6
[4,] 675556.9 811777.4 415056.6      0.0

そのため、vill_id = 100 のすべてのポイントの対称距離マトリックスが生成されました。平均距離を計算するには、この行列を分解する (またはすべての対角値 (0) を削除する) 必要があります。

> diag(dist_100_2) = NA
> dist_100_2_final <- dist_100_2[!is.na(dist_100_2)]
> dist_100_2_final
 [1] 141844.7 693867.8 675556.9 141844.7 787217.4 811777.4 693867.8 787217.4 415056.6 675556.9
[11] 811777.4 415056.6
> mean(dist_100_2_final)
[1] 587553.5 (in m)

ここまでは順調ですね。次に、同じ ID を持つすべてのサブセットの平均距離を格納する新しいデータフレームを作成する必要があります (元のデータベースには 200 を超える村 (vill_id) とほぼ 2000 の世帯 (hh_id) があります)。コードを完成させる方法を教えてください。ループを使用する必要があると思います (または、この問題を解決する別のパッケージがあるかもしれません)。助けてくれて本当にありがとうございます。

昨日、同じような質問を投稿しましたが、mean_dist が既に元のデータフレーム (ArcGIS で計算) の一部であったという違いがありますが、結果を比較するために R でこれらを計算したいと考えています。以前の質問の推奨コードを実装しようとしましたが、成功しませんでした。

4

2 に答える 2

0

さまざまなレベルの要素 (つまりvill_idby )にわたって操作を実行する必要があるため、ベース R を検討してください。内部では、1 つのデータフレームに行バインドできるデータフレームのリストを返す、定義済み関数または無名関数を呼び出すことができます。by

dfList <- by(df, df[c("vill_id")], FUN = function(i){
     sub <- i[, c(1, 2)]
     tmp <- distm(sub, fun = distVincentyEllipsoid)
     diag(tmp) = NA
     i$mean_dist <- mean(tmp[!is.na(tmp)])                  # NEW COLUMN ADDED
     return(i)
})

finaldf <- do.call(rbind, dfList)

vill_idhh_idのサブセットが必要な場合は、要素リストに追加します。

dfList <- by(df, df[c("vill_id", "hh_id")], FUN = function(i){ ... })

また、関数から返されたvill_idmean_distのみが必要な場合は、戻り値を変更します。

newdf <- unique(i[c("vill_id", "mean_dist")]
return(newdf)

具体的には、次のコード ブロック:

df_100 <- df[df$vill_id == 100, ]                            # BY REPLACES THIS LINE
df_100_2 <- df_100[, c(1, 2)]
dist_100_2 <- distm(df_100_2, fun = distVincentyEllipsoid)                 
diag(dist_100_2) = NA
dist_100_2_final <- dist_100_2[!is.na(dist_100_2)]
mean(dist_100_2_final)

iby関数変数である場合、次のように変換されます。

sub <- i[,c(1, 2)]
tmp <- distm(sub, fun = distVincentyEllipsoid)
diag(tmp) = NA
i$mean_dist <- mean(tmp[!is.na(tmp)])
于 2017-05-21T14:12:48.067 に答える