0Pricing
R Academy · درس

الضمليات والعمليات المكانية

طبّق st_join() وst_intersection() وst_buffer() وst_distance()

الضمليات والعمليات المكانية درس مجاني في R Academy على CoddyKit. هذا هو الدرس 3 من أصل 4. يمكنك قراءة الدرس كاملاً أدناه مجاناً — ثم تمرن عليه مباشرة في المتصفح باستخدام محرر أكواد مدمج ومدرس ذكاء اصطناعي متاح 24/7. هذا الدرس جزء من مسار التعلم في R Academy، وتقدمك يتزامن عبر الويب وتطبيق CoddyKit. تتضمن دورة R Academy 4 دروس في المجموع.

عمليات الربط المكاني باستخدام st_join

تنفّذ st_join(x, y) عملية ربط مكاني يسارية: فلكل معلم في x، تبحث عن المعالم في y التي تحقق مسندًا مكانيًا، والمسند الافتراضي هو st_intersects، ثم تضيف سماتها. وتؤدي المطابقات المتعددة إلى إنشاء صفوف متعددة.

library(sf)

nc <- st_transform(
  read_sf(system.file('shape/nc.shp', package = 'sf')), 4326
)

# Create random points within NC bounding box
set.seed(42)
bbox <- st_bbox(nc)
pts <- data.frame(
  lon = runif(20, bbox['xmin'], bbox['xmax']),
  lat = runif(20, bbox['ymin'], bbox['ymax'])
)
pts_sf <- st_as_sf(pts, coords = c('lon', 'lat'), crs = 4326)

# Spatial join: assign county attributes to each point
pts_with_county <- st_join(pts_sf, nc['NAME'])

cat('Points with county:\n')
print(head(pts_with_county[, c('NAME', 'geometry')], 5))

st_within: النقطة داخل المضلع

تعيد st_within(x, y) مصفوفة متناثرة من القيم المنطقية التي تشير إلى ما إذا كان كل معلم في x يقع بالكامل داخل معلم في y. وهي أكثر صرامة من st_intersects؛ إذ لا تُحتسب ملامسة الحدود.

library(sf)

nc <- st_transform(
  read_sf(system.file('shape/nc.shp', package = 'sf')), 4326
)

# Random points
set.seed(7)
bbox <- st_bbox(nc)
pts_sf <- st_as_sf(
  data.frame(
    lon = runif(30, bbox['xmin'], bbox['xmax']),
    lat = runif(30, bbox['ymin'], bbox['ymax'])
  ),
  coords = c('lon', 'lat'), crs = 4326
)

# Which points are within NC at all?
within_nc <- st_within(pts_sf, st_union(nc), sparse = FALSE)[, 1]
cat('Points within NC:', sum(within_nc), '/ 30\n')

# Keep only points inside NC
pts_inside <- pts_sf[within_nc, ]
cat('Kept:', nrow(pts_inside), 'points\n')

st_intersects: اختبار التداخل

تعيد st_intersects(x, y) القيمة TRUE عندما يشترك المعلمان في أي جزء هندسي، سواء عند الحدود أو في الداخل. وهو المسند الطوبولوجي الأكثر تساهلًا. مرّروا sparse = FALSE للحصول على مصفوفة منطقية بدلًا من قائمة بمتجهات الفهارس.

library(sf)

# Create two overlapping polygons
poly1 <- st_polygon(list(matrix(c(0,0, 2,0, 2,2, 0,2, 0,0), ncol=2, byrow=TRUE)))
poly2 <- st_polygon(list(matrix(c(1,1, 3,1, 3,3, 1,3, 1,1), ncol=2, byrow=TRUE)))
poly3 <- st_polygon(list(matrix(c(5,5, 6,5, 6,6, 5,6, 5,5), ncol=2, byrow=TRUE)))

sfc <- st_sfc(poly1, poly2, poly3, crs = 32119)

# Intersects matrix
mat <- st_intersects(sfc, sparse = FALSE)
cat('Intersects matrix:\n')
print(mat)
cat('\npoly1 intersects poly2:', mat[1, 2], '\n')
cat('poly1 intersects poly3:', mat[1, 3], '\n')

st_buffer: إنشاء مناطق عازلة

تنشئ st_buffer(sf_obj, dist) مضلعًا عازلًا حول كل معلم على المسافة المحددة. وفي CRS جغرافي تكون المسافة بالدرجات، أما في CRS مسقط فتكون بالأمتار؛ لذلك أعيدوا الإسقاط دائمًا قبل إنشاء المناطق العازلة للحصول على نتائج دقيقة.

library(sf)

# City points in WGS84
cities <- data.frame(
  city = c('Raleigh', 'Charlotte', 'Greensboro'),
  lon  = c(-78.639, -80.843, -79.792),
  lat  = c(35.779,  35.227,  36.073)
)
cities_sf <- st_as_sf(cities, coords = c('lon', 'lat'), crs = 4326)

# Project to metres for accurate buffering (NC State Plane)
cities_proj <- st_transform(cities_sf, 32119)

# 25 km buffer around each city
buffers <- st_buffer(cities_proj, dist = 25000)

cat('Buffer geometry type:', unique(as.character(st_geometry_type(buffers))), '\n')
cat('Buffer area (km2):', round(as.numeric(st_area(buffers[1, ])) / 1e6, 2), '\n')
cat('Expected (pi*25^2):', round(pi * 25^2, 2), 'km2\n')

st_area: مساحات المضلعات

تحسب st_area(sf_obj) مساحة كل مضلع. وفي CRS جغرافي تعيد قيمًا بالستيراديان، وهي غير مفيدة؛ أما في CRS مسقط بوحدات المتر، فتعيد أمتارًا مربعة. وتحمل النتائج الوحدات من حزمة units.

library(sf)
library(units)

nc <- read_sf(system.file('shape/nc.shp', package = 'sf'))
nc_proj <- st_transform(nc, 32119)  # NC State Plane, metres

# Area in m2 with units
nc_proj$area_m2 <- st_area(nc_proj)

# Convert to km2
nc_proj$area_km2 <- set_units(nc_proj$area_m2, 'km^2')

# Summary statistics
cat('Smallest county:', nc_proj$NAME[which.min(nc_proj$area_km2)],
    round(min(as.numeric(nc_proj$area_km2)), 1), 'km2\n')
cat('Largest county: ', nc_proj$NAME[which.max(nc_proj$area_km2)],
    round(max(as.numeric(nc_proj$area_km2)), 1), 'km2\n')

st_distance: المسافات بين الأزواج

تحسب st_distance(x, y) مصفوفة المسافات بين جميع المعالم في x وجميع المعالم في y. وتستخدم المسافات الجيوديسية في WGS84، والمسافات الإقليدية في CRS مسقط. وتحمل النتائج بيانات وصفية عن units.

library(sf)

cities <- data.frame(
  city = c('Raleigh', 'Charlotte', 'Greensboro', 'Wilmington'),
  lon  = c(-78.639, -80.843, -79.792, -77.909),
  lat  = c(35.779,  35.227,  36.073,  34.226)
)
cities_sf <- st_as_sf(cities, coords = c('lon', 'lat'), crs = 4326)

# Geodesic distance matrix (metres)
dist_m <- st_distance(cities_sf)
dist_km <- round(dist_m / 1000)

rownames(dist_km) <- cities$city
colnames(dist_km) <- cities$city

cat('Distance matrix (km):\n')
print(dist_km)

# Nearest neighbour for Raleigh
raleigh_dist <- as.numeric(dist_km['Raleigh', -1])
cat('\nNearest to Raleigh:',
    cities$city[-1][which.min(raleigh_dist)],
    min(raleigh_dist), 'km\n')

st_union: دمج الأشكال الهندسية

تدمج st_union(sf_obj) جميع المعالم في شكل هندسي واحد، وتزيل الحدود الداخلية. وتفيد في إنشاء مضلع بحد خارجي واحد من عدة مضلعات للمقاطعات، أو في دمج مجموعة من المناطق العازلة.

library(sf)

nc <- st_transform(
  read_sf(system.file('shape/nc.shp', package = 'sf')), 32119
)

# Dissolve all counties into the NC state outline
nc_state <- st_union(nc)

cat('Counties before union:', nrow(nc), '\n')
cat('Features after union:', length(nc_state), '(single geometry)\n')
cat('Geometry type:', as.character(st_geometry_type(nc_state)), '\n')

# Area check: sum of counties == state area
county_area_sum <- sum(as.numeric(st_area(nc)))
state_area     <- as.numeric(st_area(nc_state))
cat('Sum of county areas:', round(county_area_sum / 1e9, 2), 'km2\n')
cat('State area:         ', round(state_area     / 1e9, 2), 'km2\n')

st_intersection: القص

تعيد st_intersection(x, y) التقاطع الهندسي لكل زوج من المعالم، أي المساحة المشتركة بين الشكلين الهندسيين. وتُستخدم لقص طبقة بحيث تقتصر على نطاق طبقة أخرى.

library(sf)

nc <- st_transform(
  read_sf(system.file('shape/nc.shp', package = 'sf')), 4326
)

# Clip NC counties to a bounding rectangle (eastern NC)
clip_box <- st_as_sfc(st_bbox(c(
  xmin = -78, xmax = -75,
  ymin = 33.5, ymax = 36.5
), crs = 4326))

eastern_nc <- st_intersection(nc, clip_box)
cat('Original features:', nrow(nc), '\n')
cat('Clipped features: ', nrow(eastern_nc), '\n')
cat('Geometry types:   ', paste(unique(as.character(st_geometry_type(eastern_nc))), collapse = ', '), '\n')

التجميع المكاني باستخدام dplyr

يمكنكم دمج st_join() مع dplyr::group_by() وsummarise() لتجميع بيانات النقاط حسب المضلع. ويُلخَّص عمود الشكل الهندسي تلقائيًا، إذ يُدمج افتراضيًا، عند تجميع كائن sf.

library(sf)
library(dplyr)

nc <- st_transform(
  read_sf(system.file('shape/nc.shp', package = 'sf')), 4326
)

# Generate random sales events in NC
set.seed(99)
bbox <- st_bbox(nc)
pts <- st_as_sf(
  data.frame(
    lon   = runif(200, bbox['xmin'], bbox['xmax']),
    lat   = runif(200, bbox['ymin'], bbox['ymax']),
    sales = runif(200, 100, 1000)
  ),
  coords = c('lon', 'lat'), crs = 4326
)

# Join then aggregate
result <- st_join(pts, nc['NAME']) |>
  filter(!is.na(NAME)) |>
  st_drop_geometry() |>
  group_by(NAME) |>
  summarise(total_sales = sum(sales), n_events = n()) |>
  arrange(desc(total_sales))

cat('Top 5 counties by sales:\n')
print(head(result, 5))

st_nearest_feature

تعيد st_nearest_feature(x, y) فهرس أقرب معلم في y لكل معلم في x. وبدمجها مع st_distance()، تحصلون على الجار الأقرب ومسافته معًا، وهو أمر مفيد في مسائل الإسناد.

library(sf)

# Hospitals (facilities)
hospitals <- data.frame(
  name = c('Hospital A', 'Hospital B', 'Hospital C'),
  lon  = c(-79.5, -80.2, -78.8),
  lat  = c(35.8,  35.3,  36.1)
)
hosp_sf <- st_as_sf(hospitals, coords = c('lon', 'lat'), crs = 4326)

# Patient locations
patients <- data.frame(
  id  = 1:5,
  lon = c(-79.9, -80.5, -79.0, -78.5, -80.1),
  lat = c(35.7,  35.2,  35.9,  35.5,  36.0)
)
pt_sf <- st_as_sf(patients, coords = c('lon', 'lat'), crs = 4326)

# Find nearest hospital for each patient
nearest_idx <- st_nearest_feature(pt_sf, hosp_sf)
pt_sf$nearest_hospital <- hospitals$name[nearest_idx]

print(st_drop_geometry(pt_sf))

سير عمل عملي: إنشاء منطقة عازلة والعد

من الأنماط الشائعة في الواقع: إنشاء منطقة عازلة حول مجموعة من المعالم، مثل المدارس، ثم عدّ عدد نقاط الاهتمام، مثل مواقف الحافلات، الواقعة داخل كل منطقة عازلة باستخدام st_join() وdplyr::count().

library(sf)
library(dplyr)

# Schools as points
schools <- data.frame(
  id  = 1:3,
  lon = c(-79.8, -80.2, -79.4),
  lat = c(35.9,  35.5,  36.1)
)
schools_sf <- st_as_sf(schools, coords = c('lon', 'lat'), crs = 4326) |>
  st_transform(32119)  # project to metres

# Random bus stops
set.seed(5)
stops <- data.frame(
  stop_id = 1:50,
  lon = rnorm(50, -79.8, 0.3),
  lat = rnorm(50,  35.8, 0.2)
) |>
  st_as_sf(coords = c('lon', 'lat'), crs = 4326) |>
  st_transform(32119)

# 2 km buffer around each school
buffers <- st_buffer(schools_sf, dist = 2000)
buffers$school_id <- schools$id

# Count bus stops within each school buffer
joined <- st_join(stops, buffers['school_id'])
counts <- count(st_drop_geometry(joined), school_id)
cat('Bus stops within 2km:\n')
print(counts)

تحقق سريع

تريدون العثور على جميع المعالم المضلعة من الطبقة B التي تتداخل مع كل مضلع في الطبقة A، وإضافة سمات B إلى A. ما الدالة التي ينبغي استخدامها؟

مراجعة: عمليات الربط المكاني والمعالجة المكانية

أهم النقاط:

  • st_join(x, y) — ربط مكاني يساري باستخدام مسند، والافتراضي هو st_intersects
  • st_within() — تعيد TRUE عندما يكون x داخل y بالكامل، مع استبعاد الحدود
  • st_intersects() — تعيد TRUE عندما يلامس أي جزء من x عنصر y، وهي الأكثر تساهلًا
  • st_buffer(sf_obj, dist) — تنشئ مناطق عازلة؛ استخدموا CRS مسقطًا للحصول على مناطق عازلة دقيقة بالأمتار
  • st_area() / st_distance() — تحسب المساحات والمسافات، مع إعادة الإسقاط أولًا لتحقيق الدقة
  • st_union() — تدمج جميع المعالم؛ وst_intersection() — تقص طبقة وفق طبقة أخرى
  • st_nearest_feature(x, y) — البحث عن أقرب جار
library(sf)
nc <- st_transform(
  read_sf(system.file('shape/nc.shp', package = 'sf')), 32119
)

# Quick operations summary
cat('Largest county:', nc$NAME[which.max(st_area(nc))], '\n')
nc_outline <- st_union(nc)
cat('State area km2:', round(as.numeric(st_area(nc_outline)) / 1e6, 0), '\n')

الأسئلة الشائعة

هل درس «الضمليات والعمليات المكانية» مجاني؟

نعم — نص درس «الضمليات والعمليات المكانية» كامل متاح مجاناً هنا على الويب. لتمرينه بشكل تفاعلي (محرر أكواد مدمج ومدرس ذكاء اصطناعي متاح 24/7) وفتح باقي دورة R Academy، انتقل إلى CoddyKit PRO. تتضمن دورة R Academy 4 دروس في المجموع.

ماذا ستتعلم في «الضمليات والعمليات المكانية»؟

طبّق st_join() وst_intersection() وst_buffer() وst_distance() تتمرن على R Academy مع أكواد عملية تشغلها مباشرة في المتصفح، ومدرس ذكاء اصطناعي متاح 24/7 يجيب على أسئلتك أثناء عملك.

هل أحتاج إلى خبرة سابقة لأبدأ R Academy؟

لا تُشترط خبرة سابقة. R Academy على CoddyKit منظم للمبتدئين حتى المتقدمين، لذا يمكنك البدء من هنا أو من البداية والتقدم بسرعتك الخاصة. هذا هو الدرس 3 من أصل 4.

كم من الوقت يستغرق درس «الضمليات والعمليات المكانية»؟

معظم دروس CoddyKit تستغرق حوالي 5–10 دقائق. كل منها موجز وتفاعلي، لذا تحرز تقدماً مستمراً وتستأنف من حيث توقفت عبر الويب والتطبيق.

هل يمكنني كتابة وتشغيل أكواد في درس R Academy هذا؟

نعم. كل درس في R Academy يتضمن محرر أكواد مدمج، لذا تكتب وتشغل أكواداً حقيقية مباشرة في متصفحك وتحصل على تعليقات فورية من الذكاء الاصطناعي — بدون إعداد محلي.

جميع الدروس في هذه الدورة

  1. السمات البسيطة باستخدام حزمة sf
  2. أنظمة الإسناد والإسقاطات الإحداثية
  3. الضمليات والعمليات المكانية
  4. الخرائط التفاعلية باستخدام leaflet
← العودة إلى R Academy