R: R والخرائط والبيانات المكانية
آخر تحديث: 2026-08-26
البيانات الجغرافية المكانية تزداد أهميتها يومًا بعد يوم في المشاريع الواقعية — مثل خرائط الجائحة، وخرائط التوزيع اللوني لطلبات سيارات الأجرة عبر تطبيق «ديدي»، ومناطق تغطية خدمات التوصيل الخاصة بـ «JD.com». في هذا الدرس، سنتعرف على تصور الخرائط في لغة R: باستخدام حزمة sf لمعالجة البيانات المتجهة، وحزمة ggplot2 لإنشاء الخرائط، وحزمة Leaflet لإنشاء خرائط تفاعلية.
بعد الانتهاء من هذا الدرس، ستتمكن من إنشاء أربعة أنواع من الخرائط باستخدام لغة R: الخرائط الثابتة (ggplot2 + sf)، والخرائط الكوروبليثية، وخرائط كثافة النقاط، والخرائط التفاعلية (leaflet).
1. ما ستتعلمه
- أساسيات البيانات المكانية (البيانات المتجهة/النقطية، ملفات Shapefile، أنظمة الإحداثيات)
- تقوم حزمة sf بقراءة ملفات shapefile ومعالجتها
- إنشاء الخرائط باستخدام ggplot2 و geom_sf
- أنظمة الإحداثيات CRS (WGS84 / Web Mercator)
- خريطة كوروبليث
- خريطة تفاعلية في النشرة الإعلانية
- في الواقع العملي: خرائط توزيع المبيعات في المدن الصينية
2. القصة وراء خريطة الحرارة اللوجستية
(1) المشكلة: تفتقر بيانات المبيعات إلى إعطاء فكرة عن الحجم
أليس هي المسؤولة عن المبيعات على الصعيد الوطني. سأل المدير: «أي مقاطعة حققت أفضل مبيعات؟» وبعد أن أمعن النظر في جدول البيانات لبعض الوقت، قال المدير: «أرني خريطة».
(2) الحل باستخدام لغة R
library(sf)
library(ggplot2)
# 1. View a Map of China
china <- st_read("china.shp")
# 2. Consolidate Sales Data
china_sales <- china |>
left_join(sales_by_province, by = c("name" = "province"))
# 3. Line Chart of Categorical Statistics
ggplot(china_sales) +
geom_sf(aes(fill = sales)) +
scale_fill_gradient(low = "lightblue", high = "darkred") +
labs(title = "National Sales Distribution", fill = "Sales")
3 أسطر من التعليمات البرمجية → خريطة لمبيعات الصين بجودة النشر.
3. أساسيات البيانات المكانية
(1) الصور المتجهة مقابل الصور النقطية
graph LR
A[Spatial Data] --> B[Vector Data<br/>Vector]
A --> C[Raster Data<br/>Raster]
B --> D[pt Point<br/>Line<br/>Polygon]
C --> E[Pixel Pixel<br/>Satellite image/Temperature Map]
style A fill:#fff3cd
style B fill:#cce5ff
style C fill:#d4edda
يتناول هذا الدرس البيانات المتجهة (النقاط، والخطوط، والأسطح).
(2) ما هو ملف الشكل؟
Shapefile = معيار البيانات المتجهة الخاص بشركة ESRI، ويتألف من أربعة ملفات:
data/
├── china.shp # Geometric Information (Coordinates)
├── china.shx # Shape Index
├── china.dbf # Property Information (Name, Population, etc.)
└── china.prj # Projection Information (Coordinate System)
GeoJSON
تستخدم خرائط الويب الحديثة عادةً GeoJSON (المستند إلى JSON):
{
"type": "Feature",
"properties": {"name": "Beijing", "value": 1000},
"geometry": {
"type": "Point",
"coordinates": [116.4, 39.9]
}
}
4. حزمة sf: إطار عمل البيانات المكانية
(1) لماذا نستخدم SF؟
| الحقيبة | الميزات | التوصية |
|---|---|---|
| sf | حديث، بأسلوب R tidyverse، مع تكامل مع ggplot2 | ⭐⭐⭐ |
| sp | النمط القديم، بناء الجملة الأساسي في لغة R | ❌ غير موصى به في الكود الجديد |
| نقطية | للبيانات النقطية فقط | للنقطية |
(2) التركيب والتحميل
install.packages("sf")
library(sf)
(3) قراءة ملف الشكل
library(sf)
# Read shapefile
china <- st_read("data/china.shp")
# Reading layer `china' from data source `data/china.shp' using driver `ESRI Shapefile'
# Simple feature collection with 34 features and 5 fields
# Geometry type: MULTIPOLYGON
# Dimension: XY
# Bounding box: xmin: 73.5 ymin: 3.5 xmax: 135 ymax: 53.5
# CRS: 4326 ← WGS84 Latitude and Longitude
# View Structure
print(china)
# It basically means data.frame More geometry col
# A tibble: 34 × 6
# name population ... geometry
# <chr> <int> <MULTIPOLYGON>
# Geometric Information
st_geometry(china)
st_crs(china) # Coordinate System
st_bbox(china) # Bounding Box
(4) قراءة ملف GeoJSON
# Read GeoJSON
cities <- st_read("data/cities.geojson")
# or from URL
cities <- st_read("https://example.com/cities.geojson")
(5) كتابة ملف Shapefile / GeoJSON
# Write shapefile
st_write(china, "output/china_new.shp")
# Write GeoJSON
st_write(china, "output/china.geojson")
5. نظام الإحداثيات CRS
(1) ما هو نظام CRS؟
نظام الإحداثيات المرجعية (CRS) — تحويل سطح الأرض «الكروي» إلى «مستوى»:
graph LR
A[Earth's Surface] -->|WGS84 4326<br/>Latitude and Longitude| B[Cartesian coordinates]
A -->|Web Mercator 3857<br/>m| B
A -->|China 2000<br/>m| B
(2) رموز CRS الشائعة
| EPSG | الاسم | الغرض |
|---|---|---|
| 4326 | WGS84 | GPS / عام (الأكثر شيوعًا) |
| 3857 | خريطة ميركاتور على الويب | خرائط جوجل، OpenStreetMap |
| 4490 | CGCS2000 | نظام الإحداثيات الوطني الصيني |
| 32650 | UTM 50N | موقع محلي عالي الدقة |
(3) تحويل نظام الإحداثيات
# View Current CRS
st_crs(china)
# Coordinate Reference System:
# EPSG: 4326
# proj4string: "+proj=longlat +datum=WGS84 ..."
# Convert to Web Mercator (3857)
china_3857 <- st_transform(china, 3857)
# Convert to China 2000
china_4490 <- st_transform(china, 4490)
(4) استخراج خطوط العرض والطول
# Extracting Latitude and Longitude from Geometric Objects
coords <- st_coordinates(china)
# X = Longitude, Y = Latitude
6. إنشاء الخرائط باستخدام ggplot2 و geom_sf
(1) الخريطة الأساسية
library(ggplot2)
library(sf)
ggplot(china) +
geom_sf() +
labs(title = "Map of China")
(2) تلوين الخرائط (التلوين حسب السمة)
# Color by Province
ggplot(china) +
geom_sf(aes(fill = name)) +
labs(title = "Provinces of China", fill = "Province") +
theme_minimal()
(3) التبسيط الهندسي (تحسين الأداء)
# World Map (>100,000 coordinate points) use st_simplify to simplify
china_simple <- st_simplify(china, dTolerance = 1000)
# Drawing (10x faster)
ggplot(china_simple) + geom_sf()
(4) تخصيص السمة
ggplot(china) +
geom_sf(fill = "lightblue", color = "white", linewidth = 0.3) +
labs(title = "Map of China") +
theme_void() + # Hide Axes
theme(
plot.title = element_text(face = "bold", hjust = 0.5),
legend.position = "none"
)
7. خريطة الكوروبليث
(1) دمج البيانات + إنشاء مخطط تصنيفي
# Simulated Sales Data
sales_by_province <- data.frame(
name = c("Beijing", "Shanghai", "Guangdong", "Jiangsu", "Zhejiang", "Sichuan", "Hubei", "Shaanxi"),
sales = c(5000, 4500, 4000, 3500, 3000, 2500, 2000, 1500)
)
# Merge into Map
china_sales <- china |>
left_join(sales_by_province, by = "name")
# Draw a categorical bar chart
ggplot(china_sales) +
geom_sf(aes(fill = sales), color = "white", linewidth = 0.3) +
scale_fill_gradient(
low = "lightyellow",
high = "darkred",
na.value = "gray90"
) +
labs(title = "National Sales Distribution", fill = "Sales (10,000 yuan)") +
theme_void() +
theme(
plot.title = element_text(face = "bold", hjust = 0.5, size = 16),
legend.position = "right"
)
(2) التصنيف (مستمر → منفصل)
# Use cut to divide continuous values into 5 levels
china_sales <- china_sales |>
mutate(sales_level = cut(sales,
breaks = c(0, 1000, 2000, 3000, 5000),
labels = c("Low", "Mid", "High", "Very high"),
include.lowest = TRUE))
ggplot(china_sales) +
geom_sf(aes(fill = sales_level), color = "white", linewidth = 0.3) +
scale_fill_brewer(palette = "YlOrRd", na.value = "gray90") +
labs(title = "National Sales Grades", fill = "Level") +
theme_void()
8. مخطط كثافة النقاط
# City Points (Latitude and Longitude + Sales)
cities <- data.frame(
name = c("Beijing", "Shanghai", "Guangzhou", "Shenzhen"),
lon = c(116.4, 121.5, 113.3, 114.1),
lat = c(39.9, 31.2, 23.1, 22.5),
sales = c(5000, 4500, 4000, 3000)
) |>
st_as_sf(coords = c("lon", "lat"), crs = 4326)
# Draw a point on the map
ggplot() +
geom_sf(data = china, fill = "lightgray", color = "white") +
geom_sf(data = cities, aes(size = sales), color = "red", alpha = 0.7) +
scale_size_continuous(range = c(2, 12), name = "Sales") +
labs(title = "Map of City Sales Locations") +
theme_void()
9. الخريطة التفاعلية في Leaflet
(1) التثبيت والأساسيات
install.packages("leaflet")
library(leaflet)
# Basic Interactive Map
m <- leaflet() |>
addTiles() |> # OpenStreetMap Base Map
setView(lng = 116.4, lat = 39.9, zoom = 4) # Beijing as the center
m # Show in RStudio Viewer
(2) إضافة علامة (تسمية)
# Add a city
leaflet(cities) |>
addTiles() |>
addMarkers(
lng = ~lon, lat = ~lat,
popup = ~paste0("<b>", name, "</b><br>Sales: ", sales, " 10,000 yuan"),
label = ~name
)
(3) إضافة دوائر (حسب الحجم)
leaflet(cities) |>
addTiles() |>
addCircles(
lng = ~lon, lat = ~lat,
radius = ~sqrt(sales) * 1000, # By Sales Radius
color = "red",
fillOpacity = 0.5,
popup = ~paste0(name, ": ", sales, "10,000 yuan")
)
(4) التلوين المتدرج
# Use sf Data
leaflet(china_sales) |>
addTiles() |>
addPolygons(
fillColor = ~colorNumeric("YlOrRd", sales)(sales),
fillOpacity = 0.7,
color = "white",
weight = 1,
popup = ~paste0("<b>", name, "</b><br>Sales: ", sales, " 10,000 yuan")
) |>
addLegend(pal = colorNumeric("YlOrRd", china_sales$sales),
values = ~sales, title = "Sales")
(5) حفظ بتنسيق HTML
# Save as a standalone HTML file (Shareable)
library(htmlwidgets)
saveWidget(m, "interactive_map.html", selfcontained = FALSE)
10. مثال كامل: خريطة توزيع المبيعات على المستوى الوطني
فيما يلي مثال على مسار عمل كامل يربط بين جميع المفاهيم المتعلقة بالخرائط التي تم تناولها في هذا الدرس.
▶ مثال: 4 خرائط مبيعات للمدن (ثابتة + تفاعلية)
# ============================================
# 4 City Sales Map
# Features: ggplot2 Static Map + leaflet Interactive Map
# ============================================
library(sf)
library(ggplot2)
library(dplyr)
library(leaflet)
library(htmlwidgets)
# 1. Prepare data
# 4 City Points (Latitude and Longitude)
cities <- data.frame(
name = c("Beijing", "Shanghai", "Guangzhou", "Shenzhen"),
lon = c(116.4074, 121.4737, 113.2644, 114.0579),
lat = c(39.9042, 31.2304, 23.1291, 22.5431),
sales = c(5000, 4500, 4000, 3000),
region = c("Northern China", "East China", "South China", "South China")
) |>
st_as_sf(coords = c("lon", "lat"), crs = 4326)
# Simplified Polygons of China's Provinces (Sample data here)
china_provinces <- data.frame(
name = c("Beijing", "Shanghai", "Guangdong Province"),
lat = c(39.9, 31.2, 23.1),
lon = c(116.4, 121.5, 113.3)
)
# 2. Static Map: ggplot2 + sf
p_static <- ggplot() +
# Simplify: use geom_point Replace geom_sf (no shapefile)
borders(database = "world", regions = "China",
fill = "lightgray", color = "white") +
geom_sf(data = cities, aes(size = sales, color = region),
alpha = 0.7) +
geom_text(data = as.data.frame(st_coordinates(cities)),
aes(X, Y, label = cities$name),
vjust = -1.5, size = 4, fontface = "bold") +
scale_size_continuous(range = c(3, 12), name = "Sales (10,000 yuan)") +
scale_color_brewer(palette = "Set1", name = "Region") +
labs(title = "China 4 Sales Distribution in Major Cities",
subtitle = "Data: 2024 Q4",
caption = "Base Map: Natural Earth | Chart: R + ggplot2") +
coord_sf(xlim = c(100, 125), ylim = c(20, 45)) +
theme_minimal() +
theme(
plot.title = element_text(face = "bold", hjust = 0.5, size = 16),
plot.subtitle = element_text(hjust = 0.5, color = "gray40"),
legend.position = "bottom"
)
print(p_static)
# 3. Save Static Image
ggsave("static_sales_map.png", p_static,
width = 10, height = 8, dpi = 300)
cat("=== The static map has been saved: static_sales_map.png ===\n")
# 4. Interactive Map: leaflet
cities_df <- as.data.frame(st_coordinates(cities)) |>
rename(lon = X, lat = Y) |>
cbind(name = cities$name, sales = cities$sales, region = cities$region)
m_interactive <- leaflet(cities_df) |>
addTiles() |>
setView(lng = 114, lat = 33, zoom = 4) |>
addCircleMarkers(
lng = ~lon, lat = ~lat,
radius = ~sqrt(sales) / 5,
color = ~case_when(
region == "Northern China" ~ "red",
region == "East China" ~ "blue",
region == "South China" ~ "green"
),
fillOpacity = 0.6,
stroke = TRUE,
weight = 2,
popup = ~paste0(
"<div style='font-family: Arial; font-size: 14px;'>",
"<b>", name, "</b><br>",
"Region: ", region, "<br>",
"Sales: ", sales, " 10,000 yuan<br>",
"Longitude: ", round(lon, 2), "<br>",
"Latitude: ", round(lat, 2),
"</div>"
),
label = ~paste0(name, ": ", sales, "10,000 yuan")
) |>
addLegend(
"bottomright",
colors = c("red", "blue", "green"),
labels = c("Northern China", "East China", "South China"),
title = "Region"
) |>
addScaleBar(position = "bottomleft")
# 5. Show (in RStudio Viewer)
m_interactive
# 6. Save as HTML
saveWidget(m_interactive, "interactive_sales_map.html",
selfcontained = TRUE)
cat("=== The interactive map has been saved: interactive_sales_map.html ===\n")
# 7. Output Statistics
cat("\n=== Sales Statistics ===\n")
print(cities_df |> select(name, region, sales))
النتيجة المتوقعة:
- خريطة ثابتة (PNG، 300 نقطة في البوصة، تُظهر المبيعات وفقًا لأربعة أحجام للنقاط)
- خريطة تفاعلية (HTML، تظهر تلميحات عند تمرير الماوس فوقها)
❓ أسئلة شائعة
س: أيهما يجب أن أختار، sf أم sp؟ ج: sf (Simple Features) هو المعيار الحديث للبيانات المكانية في لغة R، ويتبع أسلوب tidyverse، ويتكامل بسلاسة مع dplyr و ggplot2. استخدم sf في الكود الجديد؛ أما الكود القديم sp فلم يعد يتم صيانته.**
س: كيف أختار بين 4326 و3857؟ ج: يُستخدم 4326 (خطوط الطول والعرض وفق نظام WGS84) للاستخدام العام + نظام تحديد المواقع العالمي (GPS)؛ أما 3857 (Web Mercator) فيُستخدم لخدمات الخرائط + Google/OSM. عادةً ما تستخدم ggplot2 + sf الإعداد 4326، بينما يستخدم Leaflet الإعداد 3857 بشكل افتراضي.**
س: أين يمكنني تنزيل ملف الشكل؟ ج:
- خريطة الصين: Alibaba Cloud DataV.GeoAtlas (https://datav.aliyun.com/portal/school/atlas/area_selector)
- خريطة العالم: الأرض الطبيعية (https://www.naturalearthdata.com/)
- خريطة مفصلة للصين: https://github.com/longwosion/geojson-map-china
family = "SimHei" إلى theme(). أو بدلاً من ذلك، يتضمن borders(database = "world", regions = "China") بالفعل الأسماء الصينية بشكل افتراضي.rayshader (التي تحول الرسوم البيانية في ggplot2 إلى رسوم ثلاثية الأبعاد) أو الرسم البياني المبعثر ثلاثي الأبعاد في plotly مع خلفية خريطة. لن نتطرق إلى التفاصيل حول هذا الموضوع في هذا الدرس.- التقارير/الأوراق البحثية التي تستخدم ggplot2 (ثابتة، بجودة مناسبة للنشر)
- موقع ويب/تطبيق يستخدم Leaflet (تفاعلي، قابل للتكبير)
- قابل للمشاركة: تصدير ملف HTML باستخدام Leaflet
📖 ملخص
- البيانات المكانية = البيانات المتجهة (النقاط/الخطوط/المضلعات) + البيانات النقطية (البكسلات)؛ يتناول هذا الدرس البيانات المتجهة
- يتكون ملف Shapefile من أربعة ملفات (.shp، و.shx، و.dbf، و.prj)؛ أما GeoJSON فهو تنسيق ويب حديث
- sf هو المعيار الحديث للبيانات المكانية في لغة R، وفقًا لأسلوب tidyverse
- أنظمة الإسناد الجغرافي (CRS) الشائعة الاستخدام: 4326 (خطوط الطول والعرض وفق نظام WGS84) / 3857 (Web Mercator)
ggplot2 +
geom_sf()لرسم الخرائط الثابتة؛ أما خرائط الكوروبليث فتستخدمaes(fill = value)+scale_fill_gradient - كتيب إرشادي للخرائط التفاعلية: addTiles (الخريطة الأساسية) + addMarkers/addCircles (النقاط) + addPolygons (المناطق)
borders(database = "world")رسم خريطة للعالم بسرعة (دون الحاجة إلى ملف Shapefile)- الحفظ:
ggsave()بتنسيق PNG/PDF للمحتوى الثابت؛saveWidget()بتنسيق HTML للمحتوى التفاعلي - تطبيقات خرائط R: التوزيع الجغرافي للأعمال، الأوبئة، الخدمات اللوجستية، توزيع العملاء، خرائط الحرارة
📝 تمارين
-
تمرين أساسي: قم بتنزيل ملف GeoJSON الخاص بمقاطعات الصين من Alibaba Cloud DataV، واستورده باستخدام
st_read()، ثم استخدمggplot() + geom_sf()لرسم خريطة أساسية للصين (دون ملء الألوان). -
السؤال الأساسي: قم بتلوين الخريطة الواردة في السؤال السابق حسب المحافظات (باستخدام
aes(fill = name))، ثم أضفtheme_void()وتصميمًا موضوعيًّا. -
تمرين أساسي: استخدم
borders(database = "world", regions = "China")+geom_point(data = cities, aes(lon, lat, size = sales))لرسم خريطة للمدن الصينية، مع إحداثيات خطوط الطول والعرض المحددة مسبقًا لأربع مدن. -
تمرين متقدم: قم بمحاكاة بيانات المبيعات لخمس مدن (بما في ذلك خطوط العرض/الطول، وأرقام المبيعات، والفئات)، واستخدم Leaflet لإنشاء خريطة تفاعلية: ① ربط أرقام المبيعات بحجم الدوائر؛ ② ربط الفئات بالألوان؛ ③ إضافة تلميحات لعرض التفاصيل؛ ④ إضافة مفتاح للرموز ومقياس. احفظ الملف بتنسيق HTML.
-
التحدي: مسار العمل الكامل — تنزيل بيانات GeoJSON الخاصة بالمقاطعات الصينية ومحاكاة بيانات المبيعات لـ 31 مقاطعة: ① دمج البيانات في الخريطة باستخدام LEFT JOIN ② استخدام
cut()لتقسيمها إلى 5 فئات ③ إنشاء مخطط إحصائي مصنف باستخدام ggplot2 ④ تنسيق المخطط (العنوان/العنوان الفرعي/الخط الصيني) ⑤ إنشاء نسخة تفاعلية باستخدام Leaflet (بما في ذلك مفتاح التوضيح) ⑥ احفظ الملف بتنسيقي PNG و HTML. التقط لقطة شاشة واحفظها.