R: R والخرائط والبيانات المكانية

آخر تحديث: 2026-08-26

البيانات الجغرافية المكانية تزداد أهميتها يومًا بعد يوم في المشاريع الواقعية — مثل خرائط الجائحة، وخرائط التوزيع اللوني لطلبات سيارات الأجرة عبر تطبيق «ديدي»، ومناطق تغطية خدمات التوصيل الخاصة بـ «JD.com». في هذا الدرس، سنتعرف على تصور الخرائط في لغة R: باستخدام حزمة sf لمعالجة البيانات المتجهة، وحزمة ggplot2 لإنشاء الخرائط، وحزمة Leaflet لإنشاء خرائط تفاعلية.

بعد الانتهاء من هذا الدرس، ستتمكن من إنشاء أربعة أنواع من الخرائط باستخدام لغة R: الخرائط الثابتة (ggplot2 + sf)، والخرائط الكوروبليثية، وخرائط كثافة النقاط، والخرائط التفاعلية (leaflet).

1. ما ستتعلمه



2. القصة وراء خريطة الحرارة اللوجستية

(1) المشكلة: تفتقر بيانات المبيعات إلى إعطاء فكرة عن الحجم

أليس هي المسؤولة عن المبيعات على الصعيد الوطني. سأل المدير: «أي مقاطعة حققت أفضل مبيعات؟» وبعد أن أمعن النظر في جدول البيانات لبعض الوقت، قال المدير: «أرني خريطة».

(2) الحل باستخدام لغة R

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) الصور المتجهة مقابل الصور النقطية

100%
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، ويتألف من أربعة ملفات:

TEXT 📖 للعرض فقط
data/
├── china.shp         # Geometric Information (Coordinates)
├── china.shx         # Shape Index
├── china.dbf         # Property Information (Name, Population, etc.)
└── china.prj         # Projection Information (Coordinate System)
⚠️ ملاحظة: يجب وضع الملفات الأربعة في نفس الدليل. ملف shp هو «الملف الرئيسي»، أما الملفات الأخرى فهي ملفات مساعدة.

GeoJSON

تستخدم خرائط الويب الحديثة عادةً GeoJSON (المستند إلى JSON):

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) التركيب والتحميل

R
install.packages("sf")
library(sf)

(3) قراءة ملف الشكل

R
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

R
# Read GeoJSON
cities <- st_read("data/cities.geojson")
# or from URL
cities <- st_read("https://example.com/cities.geojson")

(5) كتابة ملف Shapefile / GeoJSON

R
# Write shapefile
st_write(china, "output/china_new.shp")

# Write GeoJSON
st_write(china, "output/china.geojson")


5. نظام الإحداثيات CRS

(1) ما هو نظام CRS؟

نظام الإحداثيات المرجعية (CRS) — تحويل سطح الأرض «الكروي» إلى «مستوى»:

100%
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) تحويل نظام الإحداثيات

R
# 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) استخراج خطوط العرض والطول

R
# Extracting Latitude and Longitude from Geometric Objects
coords <- st_coordinates(china)
# X = Longitude, Y = Latitude


6. إنشاء الخرائط باستخدام ggplot2 و geom_sf

(1) الخريطة الأساسية

R
library(ggplot2)
library(sf)

ggplot(china) +
  geom_sf() +
  labs(title = "Map of China")

(2) تلوين الخرائط (التلوين حسب السمة)

R
# Color by Province
ggplot(china) +
  geom_sf(aes(fill = name)) +
  labs(title = "Provinces of China", fill = "Province") +
  theme_minimal()

(3) التبسيط الهندسي (تحسين الأداء)

R
# 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) تخصيص السمة

R
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) دمج البيانات + إنشاء مخطط تصنيفي

R
# 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) التصنيف (مستمر → منفصل)

R
# 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. مخطط كثافة النقاط

R
# 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) التثبيت والأساسيات

R
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) إضافة علامة (تسمية)

R
# 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) إضافة دوائر (حسب الحجم)

R
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) التلوين المتدرج

R
# 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

R
# Save as a standalone HTML file (Shareable)
library(htmlwidgets)
saveWidget(m, "interactive_map.html", selfcontained = FALSE)


10. مثال كامل: خريطة توزيع المبيعات على المستوى الوطني

فيما يلي مثال على مسار عمل كامل يربط بين جميع المفاهيم المتعلقة بالخرائط التي تم تناولها في هذا الدرس.

▶ مثال: 4 خرائط مبيعات للمدن (ثابتة + تفاعلية)

R 📖 للعرض فقط
# ============================================
# 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))
83 سطر من الكود المنطقي (تجاوز الحد 40, للعرض فقط)

النتيجة المتوقعة:



❓ أسئلة شائعة

س: أيهما يجب أن أختار، 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 بشكل افتراضي.**

س: أين يمكنني تنزيل ملف الشكل؟ ج:

س ماذا أفعل إذا ظهرت الأحرف الصينية مشوشة على الخريطة؟
ج أضف family = "SimHei" إلى theme(). أو بدلاً من ذلك، يتضمن borders(database = "world", regions = "China") بالفعل الأسماء الصينية بشكل افتراضي.
س كيف يمكنني إنشاء خريطة ثلاثية الأبعاد؟
ج استخدم حزمة rayshader (التي تحول الرسوم البيانية في ggplot2 إلى رسوم ثلاثية الأبعاد) أو الرسم البياني المبعثر ثلاثي الأبعاد في plotly مع خلفية خريطة. لن نتطرق إلى التفاصيل حول هذا الموضوع في هذا الدرس.

📖 ملخص


📝 تمارين

  1. تمرين أساسي: قم بتنزيل ملف GeoJSON الخاص بمقاطعات الصين من Alibaba Cloud DataV، واستورده باستخدام st_read()، ثم استخدم ggplot() + geom_sf() لرسم خريطة أساسية للصين (دون ملء الألوان).

  2. السؤال الأساسي: قم بتلوين الخريطة الواردة في السؤال السابق حسب المحافظات (باستخدام aes(fill = name))، ثم أضف theme_void() وتصميمًا موضوعيًّا.

  3. تمرين أساسي: استخدم borders(database = "world", regions = "China") + geom_point(data = cities, aes(lon, lat, size = sales)) لرسم خريطة للمدن الصينية، مع إحداثيات خطوط الطول والعرض المحددة مسبقًا لأربع مدن.

  4. تمرين متقدم: قم بمحاكاة بيانات المبيعات لخمس مدن (بما في ذلك خطوط العرض/الطول، وأرقام المبيعات، والفئات)، واستخدم Leaflet لإنشاء خريطة تفاعلية: ① ربط أرقام المبيعات بحجم الدوائر؛ ② ربط الفئات بالألوان؛ ③ إضافة تلميحات لعرض التفاصيل؛ ④ إضافة مفتاح للرموز ومقياس. احفظ الملف بتنسيق HTML.

  5. التحدي: مسار العمل الكامل — تنزيل بيانات GeoJSON الخاصة بالمقاطعات الصينية ومحاكاة بيانات المبيعات لـ 31 مقاطعة: ① دمج البيانات في الخريطة باستخدام LEFT JOIN ② استخدام cut() لتقسيمها إلى 5 فئات ③ إنشاء مخطط إحصائي مصنف باستخدام ggplot2 ④ تنسيق المخطط (العنوان/العنوان الفرعي/الخط الصيني) ⑤ إنشاء نسخة تفاعلية باستخدام Leaflet (بما في ذلك مفتاح التوضيح) ⑥ احفظ الملف بتنسيقي PNG و HTML. التقط لقطة شاشة واحفظها.

Web-Tutorial.com

فريق Web-Tutorial التقني

منصة دروس برمجية يديرها عدة مطورين. كل درس يتم كتابته ومراجعته بواسطة مطورين متخصصين في المجال. نعمل على ضمان دقة وموثوقية المحتوى — إذا لاحظت أي مشكلة، فيرجى إخبارنا.

100%