-
-
Notifications
You must be signed in to change notification settings - Fork 1
/
_11-ex-ja.Rmd
103 lines (82 loc) · 6.7 KB
/
_11-ex-ja.Rmd
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
```{asis 11-ex-asis1, message=FALSE}
回答するには、以下のパッケージをアタッチすることとする (他のパッケージも必要に応じてアタッチする)。
```
```{r setup11, include=FALSE}
poly_centroid = function(poly_mat) {
Origin = poly_mat[1, ] # create a point representing the origin
i = 2:(nrow(poly_mat) - 2)
T_all = lapply(i, function(x) {rbind(Origin, poly_mat[x:(x + 1), ], Origin)})
C_list = lapply(T_all, t_centroid)
C = do.call(rbind, C_list)
A = vapply(T_all, t_area, FUN.VALUE = double(1))
c(weighted.mean(C[, 1], A), weighted.mean(C[, 2], A))
}
```
```{r 11-ex-e0}
library(sf)
```
E1. 本書の GitHub リポジトリの [`11-centroid-alg.R`](https://github.com/geocompx/geocompr/blob/main/code/11-centroid-alg.R) スクリプトを読みなさい。
- ベストプラクティスのうちどれを使っているか?
- RStudio\index{RStudio} などの IDE\index{IDE} を使い、自分のパソコンでスクリプトを作成しなさい (スクリプトを 1 行ずつ打ち込み、適宜コメントを入れると良い。コピペはしない。この作業でスクリプトの入力の仕方を学ぶことができる。)。正方形ポリゴン (`poly_mat = cbind(x = c(0, 9, 9, 0, 0), y = c(0, 0, 9, 9, 0))` で作成) の例を使い、スクリプトを 1 行ずつ実行しなさい。
- 再現可能性を高めるためにはどのように変更したら良いか?
- ドキュメンテーションをより良くするためにはどうしたら良いか?
```{asis 11-ex-e1, message=FALSE}
スクリプトは論理的な場所に、適切なファイル名で保存されている。
スクリプトはコメント付きできちんと文書化されており、コードの書式も整っている。
スクリプトが再現可能である。
例えば、キーボードショートカット `Ctrl + Shift + N` (Windows) または `Cmd + Shift + N` (Mac) を使用して、`File > New File > R Script` をクリックするか、`Source` ペインの左上にある `+` アイコンをクリックします。
また、R コンソールから `file.create("11-centroid-alg.R")` というコマンドで新しい R スクリプトを作成することもできる。
このスクリプトはすでに再現可能であり、`poly_mat` というオブジェクトが必要であることを示すメッセージが表示され、もし存在しなければ、テスト用のサンプルデータセットが最初に作成される。
R を初めて使う人のために、スクリプトを実行する前に R をインストールする必要があることを示すコメントを含めることもできる。
ドキュメンテーションは、本の関連セクションへのリンクを含む、アルゴリズムのより詳細な説明で改善できるだろう。
さらに、無名関数を名前付き関数に置き換え、Roxygen2 コメントで文書化することもできる。
```
E2. 幾何アルゴリズムのセクションで、`poly_mat` のポリゴンの面積は 245 で、重心は座標 (8.8, 9.2) であると計算した。
- このアルゴリズムのスクリプトである [`11-centroid-alg.R`](https://github.com/geocompx/geocompr/blob/main/code/11-centroid-alg.R) を参照し、自分のパソコンで結果を再現しなさい (ボーナス: コピペせずに自分で入力しなさい)。
- 結果は正しいか? `poly_mat` を `st_polygon()` 関数で `sfc` オブジェクトに変換し (`poly_sfc` という名前)、`st_area()` 関数と `st_centroid()` 関数を用いて検証しなさい (ヒント: この関数は、クラス `list()` を引数に取る)。
```{r 11-ex-e}
# We can verify the answer by converting `poly_mat` into a simple feature collection
# as follows, which shows the calculations match:
x_coords = c(10, 20, 12, 0, 0, 10)
y_coords = c(0, 15, 20, 10, 0, 0)
poly_mat = cbind(x_coords, y_coords)
poly_sfc = sf::st_polygon(list(poly_mat))
sf::st_area(poly_sfc)
sf::st_centroid(poly_sfc)
# By calling the script:
# source("https://github.com/geocompx/geocompr/raw/main/code/11-centroid-alg.R")
```
E3. 我々が作成したアルゴリズム\index{あるごりずむ@アルゴリズム}は**凸包**に対してのみ動作すると記載されている。凸包を定義し (ジオメトリ操作の章を参照)、凸包でないポリゴンでアルゴリズムをテストしなさい。\index{とつほう@凸包}
```{r 11-ex-e3}
x_coords = c(10, 20, 12, 0, 0, 5, 10)
y_coords = c(0, 15, 20, 10, 0, 5, 0)
plot(x_coords, y_coords, type = "l")
poly_mat = cbind(x_coords, y_coords)
# source("https://github.com/geocompx/geocompr/raw/main/code/11-centroid-alg.R")
# Area from our script: 270
poly_sfc = sf::st_polygon(list(poly_mat))
sf::st_area(poly_sfc) # Actual area: 220
```
- ボーナス 1: なぜこの方法が凸の外皮に対してのみ機能するのかを考え、他の種類の多角形に対して機能させるためにアルゴリズムに加える必要がある変更点に注意する。
- ボーナス 2: `11-centroid-alg.R` の内容を基に、行列形式で表現された線分の全長を求めることができる、Base R 関数のみを使ったアルゴリズムを書きなさい。
<!-- Todo: add example of matrix representing a linestring, demonstrate code to verify the answer, suggest alternative functions to decompose as a bonus. -->
```{asis 11-ex-e3-bonus1}
このアルゴリズムは、正の面積値だけでなく負の面積値も持つことができる必要がある。
ボーナス 2 は読者のための練習として残しておく。
```
E4. 関数のセクションでは、`sfg` クラスの出力 (`poly_centroid_sfg()`) と `matrix` 型の出力 (`poly_centroid_type_stable()`) を生成する `poly_centroid()` 関数の異なるバージョンを作成した。
さらに、型が安定で (`sf` クラスの入力しか受け付けない) `sf` オブジェクトを返すバージョン (例えば `poly_centroid_sf()`) を作成し、関数を拡張しなさい (ヒント: `sf::st_coordinates(x)` コマンドでオブジェクト `x` を行列に変換する必要があるかもしれない)。
- `poly_centroid_sf(sf::st_sf(sf::st_sfc(poly_sfc)))` を実行し、動作するか検証しなさい
- `poly_centroid_sf(poly_mat)` を実行しようとした時、どのようなエラーメッセージが表示されたか?
```{r 11-ex-e4}
poly_centroid_sf = function(x) {
stopifnot(is(x, "sf"))
xcoords = sf::st_coordinates(x)
centroid_coords = poly_centroid(xcoords)
centroid_sf = sf::st_sf(geometry = sf::st_sfc(sf::st_point(centroid_coords)))
centroid_sf
}
poly_centroid_sf(sf::st_sf(sf::st_sfc(poly_sfc)))
poly_centroid_sf(poly_sfc)
poly_centroid_sf(poly_mat)
```