列出1000 公尺內最高速食店密度的學校

library(sf)
library(spatstat)

# 載入資料
school <- st_read("/Users/harry8995/Downloads/SCHOOL/SCHOOL.shp")
Reading layer `SCHOOL' from data source 
  `/Users/harry8995/Downloads/SCHOOL/SCHOOL.shp' using driver `ESRI Shapefile'
Simple feature collection with 148 features and 4 fields
Geometry type: POINT
Dimension:     XY
Bounding box:  xmin: 297078.6 ymin: 2763290 xmax: 312516.7 ymax: 2784542
Projected CRS: TWD97 / TM2 zone 121
fst <- st_read("/Users/harry8995/Downloads/Tpe_Fastfood/Tpe_Fastfood.shp")
Reading layer `Tpe_Fastfood' from data source 
  `/Users/harry8995/Downloads/Tpe_Fastfood/Tpe_Fastfood.shp' 
  using driver `ESRI Shapefile'
Simple feature collection with 98 features and 8 fields
Geometry type: POINT
Dimension:     XY
Bounding box:  xmin: 297198.9 ymin: 2763885 xmax: 312205.7 ymax: 2781148
Projected CRS: TWD97 / TM2 zone 121
tp_vill <- st_read("/Users/harry8995/Downloads/Taipei_Vill/Taipei_Vill.shp")
Reading layer `Taipei_Vill' from data source 
  `/Users/harry8995/Downloads/Taipei_Vill/Taipei_Vill.shp' 
  using driver `ESRI Shapefile'
Simple feature collection with 456 features and 8 fields
Geometry type: POLYGON
Dimension:     XY
Bounding box:  xmin: 296094.4 ymin: 2761518 xmax: 317198.9 ymax: 2789180
Projected CRS: TWD97 / TM2 zone 121
# 合併學校與速食店幾何點,取得整體邊界
all_points <- c(st_geometry(school), st_geometry(fst))
all_bounds <- st_bbox(all_points)

# 建立 spatstat 分析視窗
window <- owin(
  xrange = c(all_bounds["xmin"], all_bounds["xmax"]),
  yrange = c(all_bounds["ymin"], all_bounds["ymax"])
)

# 建立學校的 ppp 物件
school_ppp <- ppp(
  x = st_coordinates(school)[,1],
  y = st_coordinates(school)[,2],
  window = window,
  marks = school$Name
)

# 1. Clark-Evans 檢定
# 檢驗學校點分佈是否隨機(假設為完全空間隨機性 CSR)
ce_test <- clarkevans.test(school_ppp, correction = "none", nsim = 999)
print("Clark-Evans Test Result:")
[1] "Clark-Evans Test Result:"
print(ce_test)

    Clark-Evans test
    No edge correction
    Z-test

data:  school_ppp
R = 0.85761, p-value = 0.00092
alternative hypothesis: two-sided
# 2. Ripley’s K 函數
# 計算 K 函數並與隨機分佈比較
k_env <- envelope(school_ppp, Kest, nsim = 99, rank = 1, global = TRUE)
Generating 99 simulations of CSR  ...
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.

Done.
plot(k_env, main = "Ripley’s K Function for School Distribution", 
     xlab = "Distance (meters)", ylab = "K(r)")


# 原有程式碼:計算速食店數量
fastfood_ppp <- ppp(
  x = st_coordinates(fst)[,1],
  y = st_coordinates(fst)[,2],
  window = window,
  marks = fst$ALIAS
)

# 計算距離矩陣
dist_matrix <- spatstat.geom::crossdist(school_ppp, fastfood_ppp)

# 設定半徑 1000 公尺,計算每間學校速食店數量
radius <- 1000
fastfood_count_1000m <- apply(dist_matrix, 1, function(d) sum(d <= radius))

# 加入學校資料
school$fastfood_count_1000m <- fastfood_count_1000m

# 排序學校依速食店密度(由大到小)
school_sorted <- school[order(-school$fastfood_count_1000m), ]

# 取得前10名的密度門檻值
cutoff_value <- school_sorted$fastfood_count_1000m[10]

# 篩出所有密度 >= cutoff_value 的學校
top_schools <- school_sorted[school_sorted$fastfood_count_1000m >= cutoff_value, ]

# 輸出結果與數量確認
print(as.data.frame(top_schools[, c("Name", "fastfood_count_1000m")]))
NA
NA
NA

輸出top10學校的shapefile


# 縮短欄位名稱以符合 shapefile 限制
names(top_schools)[names(top_schools) == "fastfood_count_1000m"] <- "ff_count"

# 將中文名稱轉換為 ASCII(避免亂碼,選用此方法會替換中文為<xx>格式)
top_schools$Name <- iconv(top_schools$Name, to = "ASCII", sub = "byte")

# 或者,保留中文並指定編碼(視軟體相容性)
# top_schools$Name <- iconv(top_schools$Name, from = "UTF-8", to = "UTF-8")

# 輸出結果與數量確認
print(as.data.frame(top_schools[, c("Name", "ff_count")]))

# 儲存為 shapefile,指定編碼為 UTF-8
st_write(top_schools, "/Users/harry8995/Downloads/SCHOOL/top10_school.shp", append = FALSE, layer_options = "ENCODING=UTF-8")
Deleting layer `top10_school' using driver `ESRI Shapefile'
Writing layer `top10_school' to data source 
  `/Users/harry8995/Downloads/SCHOOL/top10_school.shp' using driver `ESRI Shapefile'
options:        ENCODING=UTF-8 
Writing 16 features with 5 fields and geometry type Point.
LS0tCnRpdGxlOiAicGFydDMiCm91dHB1dDogaHRtbF9ub3RlYm9vawotLS0KCiMjIOWIl+WHujEwMDAg5YWs5bC65YWn5pyA6auY6YCf6aOf5bqX5a+G5bqm55qE5a245qChCmBgYHtyfQpsaWJyYXJ5KHNmKQpsaWJyYXJ5KHNwYXRzdGF0KQoKIyDovInlhaXos4fmlpkKc2Nob29sIDwtIHN0X3JlYWQoIi9Vc2Vycy9oYXJyeTg5OTUvRG93bmxvYWRzL1NDSE9PTC9TQ0hPT0wuc2hwIikKZnN0IDwtIHN0X3JlYWQoIi9Vc2Vycy9oYXJyeTg5OTUvRG93bmxvYWRzL1RwZV9GYXN0Zm9vZC9UcGVfRmFzdGZvb2Quc2hwIikKdHBfdmlsbCA8LSBzdF9yZWFkKCIvVXNlcnMvaGFycnk4OTk1L0Rvd25sb2Fkcy9UYWlwZWlfVmlsbC9UYWlwZWlfVmlsbC5zaHAiKQoKIyDlkIjkvbXlrbjmoKHoiIfpgJ/po5/lupflub7kvZXpu57vvIzlj5blvpfmlbTpq5TpgornlYwKYWxsX3BvaW50cyA8LSBjKHN0X2dlb21ldHJ5KHNjaG9vbCksIHN0X2dlb21ldHJ5KGZzdCkpCmFsbF9ib3VuZHMgPC0gc3RfYmJveChhbGxfcG9pbnRzKQoKIyDlu7rnq4sgc3BhdHN0YXQg5YiG5p6Q6KaW56qXCndpbmRvdyA8LSBvd2luKAogIHhyYW5nZSA9IGMoYWxsX2JvdW5kc1sieG1pbiJdLCBhbGxfYm91bmRzWyJ4bWF4Il0pLAogIHlyYW5nZSA9IGMoYWxsX2JvdW5kc1sieW1pbiJdLCBhbGxfYm91bmRzWyJ5bWF4Il0pCikKCiMg5bu656uL5a245qCh55qEIHBwcCDnianku7YKc2Nob29sX3BwcCA8LSBwcHAoCiAgeCA9IHN0X2Nvb3JkaW5hdGVzKHNjaG9vbClbLDFdLAogIHkgPSBzdF9jb29yZGluYXRlcyhzY2hvb2wpWywyXSwKICB3aW5kb3cgPSB3aW5kb3csCiAgbWFya3MgPSBzY2hvb2wkTmFtZQopCgojIDEuIENsYXJrLUV2YW5zIOaqouWumgojIOaqoumpl+WtuOagoem7nuWIhuS9iOaYr+WQpumaqOapn++8iOWBh+ioreeCuuWujOWFqOepuumWk+maqOapn+aApyBDU1LvvIkKY2VfdGVzdCA8LSBjbGFya2V2YW5zLnRlc3Qoc2Nob29sX3BwcCwgY29ycmVjdGlvbiA9ICJub25lIiwgbnNpbSA9IDk5OSkKcHJpbnQoIkNsYXJrLUV2YW5zIFRlc3QgUmVzdWx0OiIpCnByaW50KGNlX3Rlc3QpCgojIDIuIFJpcGxleeKAmXMgSyDlh73mlbgKIyDoqIjnrpcgSyDlh73mlbjkuKboiIfpmqjmqZ/liIbkvYjmr5TovIMKa19lbnYgPC0gZW52ZWxvcGUoc2Nob29sX3BwcCwgS2VzdCwgbnNpbSA9IDk5LCByYW5rID0gMSwgZ2xvYmFsID0gVFJVRSkKcGxvdChrX2VudiwgbWFpbiA9ICJSaXBsZXnigJlzIEsgRnVuY3Rpb24gZm9yIFNjaG9vbCBEaXN0cmlidXRpb24iLCAKICAgICB4bGFiID0gIkRpc3RhbmNlIChtZXRlcnMpIiwgeWxhYiA9ICJLKHIpIikKCiMg5Y6f5pyJ56iL5byP56K877ya6KiI566X6YCf6aOf5bqX5pW46YePCmZhc3Rmb29kX3BwcCA8LSBwcHAoCiAgeCA9IHN0X2Nvb3JkaW5hdGVzKGZzdClbLDFdLAogIHkgPSBzdF9jb29yZGluYXRlcyhmc3QpWywyXSwKICB3aW5kb3cgPSB3aW5kb3csCiAgbWFya3MgPSBmc3QkQUxJQVMKKQoKIyDoqIjnrpfot53pm6Lnn6npmaMKZGlzdF9tYXRyaXggPC0gc3BhdHN0YXQuZ2VvbTo6Y3Jvc3NkaXN0KHNjaG9vbF9wcHAsIGZhc3Rmb29kX3BwcCkKCiMg6Kit5a6a5Y2K5b6RIDEwMDAg5YWs5bC677yM6KiI566X5q+P6ZaT5a245qCh6YCf6aOf5bqX5pW46YePCnJhZGl1cyA8LSAxMDAwCmZhc3Rmb29kX2NvdW50XzEwMDBtIDwtIGFwcGx5KGRpc3RfbWF0cml4LCAxLCBmdW5jdGlvbihkKSBzdW0oZCA8PSByYWRpdXMpKQoKIyDliqDlhaXlrbjmoKHos4fmlpkKc2Nob29sJGZhc3Rmb29kX2NvdW50XzEwMDBtIDwtIGZhc3Rmb29kX2NvdW50XzEwMDBtCgojIOaOkuW6j+WtuOagoeS+nemAn+mjn+W6l+WvhuW6pu+8iOeUseWkp+WIsOWwj++8iQpzY2hvb2xfc29ydGVkIDwtIHNjaG9vbFtvcmRlcigtc2Nob29sJGZhc3Rmb29kX2NvdW50XzEwMDBtKSwgXQoKIyDlj5blvpfliY0xMOWQjeeahOWvhuW6pumWgOaqu+WAvApjdXRvZmZfdmFsdWUgPC0gc2Nob29sX3NvcnRlZCRmYXN0Zm9vZF9jb3VudF8xMDAwbVsxMF0KCiMg56+p5Ye65omA5pyJ5a+G5bqmID49IGN1dG9mZl92YWx1ZSDnmoTlrbjmoKEKdG9wX3NjaG9vbHMgPC0gc2Nob29sX3NvcnRlZFtzY2hvb2xfc29ydGVkJGZhc3Rmb29kX2NvdW50XzEwMDBtID49IGN1dG9mZl92YWx1ZSwgXQoKIyDovLjlh7rntZDmnpzoiIfmlbjph4/norroqo0KcHJpbnQoYXMuZGF0YS5mcmFtZSh0b3Bfc2Nob29sc1ssIGMoIk5hbWUiLCAiZmFzdGZvb2RfY291bnRfMTAwMG0iKV0pKQoKCgpgYGAKCiMjIOi8uOWHunRvcDEw5a245qCh55qEc2hhcGVmaWxlCmBgYHtyfQoKIyDnuK7nn63mrITkvY3lkI3nqLHku6XnrKblkIggc2hhcGVmaWxlIOmZkOWItgpuYW1lcyh0b3Bfc2Nob29scylbbmFtZXModG9wX3NjaG9vbHMpID09ICJmYXN0Zm9vZF9jb3VudF8xMDAwbSJdIDwtICJmZl9jb3VudCIKCiMg5bCH5Lit5paH5ZCN56ix6L2J5o+b54K6IEFTQ0lJ77yI6YG/5YWN5LqC56K877yM6YG455So5q2k5pa55rOV5pyD5pu/5o+b5Lit5paH54K6PHh4PuagvOW8j++8iQp0b3Bfc2Nob29scyROYW1lIDwtIGljb252KHRvcF9zY2hvb2xzJE5hbWUsIHRvID0gIkFTQ0lJIiwgc3ViID0gImJ5dGUiKQoKIyDmiJbogIXvvIzkv53nlZnkuK3mlofkuKbmjIflrprnt6jnorzvvIjoppbou5/pq5Tnm7jlrrnmgKfvvIkKIyB0b3Bfc2Nob29scyROYW1lIDwtIGljb252KHRvcF9zY2hvb2xzJE5hbWUsIGZyb20gPSAiVVRGLTgiLCB0byA9ICJVVEYtOCIpCgojIOi8uOWHuue1kOaenOiIh+aVuOmHj+eiuuiqjQpwcmludChhcy5kYXRhLmZyYW1lKHRvcF9zY2hvb2xzWywgYygiTmFtZSIsICJmZl9jb3VudCIpXSkpCgojIOWEsuWtmOeCuiBzaGFwZWZpbGXvvIzmjIflrprnt6jnorzngrogVVRGLTgKc3Rfd3JpdGUodG9wX3NjaG9vbHMsICIvVXNlcnMvaGFycnk4OTk1L0Rvd25sb2Fkcy9TQ0hPT0wvdG9wMTBfc2Nob29sLnNocCIsIGFwcGVuZCA9IEZBTFNFLCBsYXllcl9vcHRpb25zID0gIkVOQ09ESU5HPVVURi04IikKYGBgCgo=