R: معالجة سلاسل R: دليل شامل لمكتبة `stringr`

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

في المشاريع العملية، يُنفق 80% من وقت تنقية البيانات على معالجة السلاسل — تنقية أرقام الهواتف، واستخراج عناوين البريد الإلكتروني، واستبدال الكلمات المفتاحية، وتقسيم السلاسل وربطها. يُوصى رسميًا باستخدام حزمة stringr في لغة R من قِبل tidyverse؛ فهي أكثر اتساقًا وأسهل في الاستخدام مقارنةً بحزمة grep/gsub القياسية في لغة R.

بعد الانتهاء من هذا الدرس، ستتمكن من استخدام لغة R لتنفيذ أي مهمة تتعلق بتنقية النصوص: التحقق من صحة أرقام الهواتف، واستخراج عناوين البريد الإلكتروني، وتقسيم النصوص، وتحليل عناوين URL.

1. ما ستتعلمه



2. قصة عن تنقية البيانات

(1) المشكلة: البيانات غير الدقيقة

بعد تلقي مجموعة من بيانات العملاء، اكتشف تشين ما يلي:

TEXT 📖 للعرض فقط
Name      Cell phone number            Email
Alice      138-0000-1234     zhangsan@163.COM
Bob      +86 139 0000 5678  lisi@example.com  
Charlie      (13900001111)    wangwu@gmail.com
Diana      138.0000.2222     zhaoliu@ qq.com
Eve      13900003333       

يجب تنظيفه حتى:

TEXT 📖 للعرض فقط
Name      Cell phone number       Email
Alice      13800001234  zhangsan@163.com
Bob      13900005678  lisi@example.com
Charlie      13900001111  wangwu@gmail.com
Diana      13800002222  zhaoliu@qq.com
Eve      13900003333  NA

إذا كنت تستخدم صيغ Excel وتقوم بإجراء تعديلات يدوية، فسيستغرق الأمر نصف ساعة؛ أما باستخدام وحدة re في لغة Python، فسيستغرق الأمر 20 سطراً من التعليمات البرمجية؛ أما باستخدام لغة R stringr

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

R
library(stringr)

# 1. Delete a Phone Number(Remove spaces,-,.,+86,())
clean_phone <- str_replace_all(phones, "[\\s\\-\\.\\(\\)\\+86]", "")

# 2. Clean Up Your Inbox(Remove spaces,Convert to lowercase)
clean_email <- str_trim(emails) |> str_to_lower()

# 3. Verify the mobile phone number format
is_valid_phone <- str_detect(clean_phone, "^1[3-9]\\d{9}$")

تم إنجاز 5 مهام تنظيف باستخدام 3 أسطر فقط من التعليمات البرمجية.

100%
graph LR
    A[Dirty Strings<br/>' 138-0000-1234 '] --> B[str_trim Remove spaces]
    B --> C[str_replace_all Remove special characters]
    C --> D[str_to_lower Use all lowercase letters]
    D --> E[str_detect Validation Format]
    E --> F[Clean String<br/>'13800001234']

    style A fill:#f8d7da
    style B fill:#fff3cd
    style C fill:#d4edda
    style D fill:#cce5ff
    style E fill:#e1d4ff
    style F fill:#d4edda


3. أساسيات السلاسل

(1) إنشاء سلاسل نصية

R
# 1. Single quotation mark
s1 <- 'Hello'

# 2. Double quotation marks
s2 <- "World"

# 3. Character vector
fruits <- c("Apple", "Banana", "Cherries")
class(fruits)
# [1] "character"

# 4. nchar Number of characters
nchar("Hello")
# [1] 5

nchar("Hello")  # UTF-8 One Chinese character 1 characters
# [1] 2

(2) paste() / paste0() — التسلسل

R
# paste Default sep = " "
paste("Hello", "World")
# [1] "Hello World"

# paste0 No separators
paste0("Hello", "World")
# [1] "HelloWorld"

# Vectorized Concatenation
paste("No.", 1:3, "Place")
# [1] "No. 1 Place" "No. 2 Place" "No. 3 Place"

# collapse Combine vectors into a single string
paste(c("A", "B", "C"), collapse = "-")
# [1] "A-B-C"


4. حزمة stringr: 5 وظائف رئيسية

100%
mindmap
    root((stringr<br/>5 Major Core Functions))
        Concatenation
            str_c
            str_glue
        Substring
            str_sub
            str_length
        Testing
            str_detect
            str_count
        Replace
            str_replace
            str_replace_all
        Split
            str_split
        Support
            str_trim
            str_pad
            str_to_upper
            str_to_lower
        Advantages
            Automated Processing NA
            API Match
            Pipe-Friendly
            tidyverse Ecology

(1) مقارنة بين stringr وـ Basic R

R الأساسي stringr المزايا
nchar() str_length() تقوم دالة stringr بمعالجة القيم «NA» تلقائيًا
paste() str_c() الاتساق + التوجيه المتجهي
substr() str_sub() يدعم الفهارس السالبة
أكثر سهولة في الاستخدام
gsub() str_replace_all() أبسط
strsplit() str_split() أسهل في الاستخدام

(2) التسلسل باستخدام str_c()

R
library(stringr)

# 1. Basic Splicing
str_c("Hello", "World", sep = " ")
# [1] "Hello World"

# 2. Multi-Parameter Concatenation
str_c("a", "b", "c", sep = "-")
# [1] "a-b-c"

# 3. Vectorized Concatenation
str_c("No.", 1:3, "Place", sep = "")
# [1] "No.1Place" "No.2Place" "No.3Place"

# 4. collapse Merge Vectors
str_c(c("A", "B", "C"), collapse = " | ")
# [1] "A | B | C"

# 5. Processing NA
str_c("Hello", NA, "World")
# [1] NA
str_c("Hello", NA, "World", na.rm = TRUE)
# [1] "HelloWorld"

(3) str_length() الطول

R
# Number of characters(Not the number of bytes)
str_length("Hello")
# [1] 5

str_length("Hello")
# [1] 2

# String Vectors
str_length(c("abc", "Hello", "Hello World"))
# [1]  3  2 12

# NA Processing
str_length(NA)
# [1] NA  ← stringr Explicit Return NA

(4) str_sub(): استخراج جزء من السلسلة

R
# 1. Extract a Substring(1-based,Including both ends)
str_sub("Hello World", 1, 5)
# [1] "Hello"

# 2. Negative Index(From the last digit)
str_sub("Hello World", -5)  # Finally 5 ea
# [1] "World"

# 3. Modify a Substring
s <- "Hello World"
str_sub(s, 1, 5) <- "Hi"
s
# [1] "Hi World"

# 4. Vectorization
str_sub(c("apple", "banana", "cherry"), 1, 3)
# [1] "app" "ban" "che"

(5) الكشف باستخدام str_detect()

R
# 1. Does it contain a substring?
str_detect("Hello World", "World")
# [1] TRUE

# 2. Using regular expressions
str_detect(c("apple", "banana", "cherry"), "^a")  # Starting with a
# [1]  TRUE FALSE FALSE

# 3. Count(Includes several times)
str_count("ababab", "ab")
# [1] 3

(6) استبدال باستخدام str_replace() / str_replace_all()

R
# 1. Replace the first match
str_replace("Hello World World", "World", "R")
# [1] "Hello R World"

# 2. Replace all matches
str_replace_all("Hello World World", "World", "R")
# [1] "Hello R R"

# 3. Using regular expressions
str_replace_all("abc 123 def 456", "\\d+", "X")
# [1] "abc X def X"


5. التعامل مع المسافات والتنسيق

(1) تزيل الدالة str_trim() المسافات البيضاء

R
# 1. Remove leading and trailing spaces
str_trim("  Hello World  ")
# [1] "Hello World"

# 2. Left edge
str_trim("  Hello", side = "left")
# [1] "Hello"

# 3. Go to the right end
str_trim("Hello  ", side = "right")
# [1] "Hello"

(2) str_pad() — ملء الفراغات

R
# 1. Left-aligned
str_pad("42", width = 5, side = "left", pad = "0")
# [1] "00042"

# 2. Right-aligned
str_pad("Hi", width = 5, side = "right", pad = "-")
# [1] "Hi---"

# 3. Filled on both sides
str_pad("Hi", width = 6, side = "both", pad = "-")
# [1] "--Hi--"

(3) حساسية str_to_* تجاه الأحرف الكبيرة والصغيرة

R
# 1. All Caps
str_to_upper("Hello World")
# [1] "HELLO WORLD"

# 2. All lowercase
str_to_lower("Hello World")
# [1] "hello world"

# 3. Capitalize the first letter
str_to_title("hello world")
# [1] "Hello World"

# 4. Capitalize the first word of a sentence
str_to_sentence("hello world")
# [1] "Hello world"

(4) str_trunc() اقتطاع

R
# Truncate excessively long strings(add ...)
str_trunc("This is a very long sentence.", width = 10)
# [1] "This is..."


6. تقسيم السلسلة باستخدام str_split()

R
# 1. Basic Division
str_split("a,b,c", ",")
# [[1]]
# [1] "a" "b" "c"

# 2. Limit on the Number of Partitions
str_split("a,b,c", ",", n = 2)
# [[1]]
# [1] "a"     "b,c"

# 3. Simplify the result(Vectors, Not Lists)
str_split("a,b,c", ",", simplify = TRUE)
#      [,1] [,2] [,3]
# [1,] "a"  "b"  "c"


7. تمرين عملي: تنظيف بيانات العملاء

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

▶ مثال: التنظيف الشامل لبيانات العملاء

R 📖 للعرض فقط
# ============================================
# In-Depth Cleaning of Customer Data
# Features:Delete a Phone Number,Email,Name,Address
# ============================================

library(stringr)
library(dplyr)

# 1. Preparing Raw Data
customers <- tibble(
  name = c("  Alice  ", "Bob", "wangwu", "ZHAO liu", "Eve"),
  phone = c("138-0000-1234", "+86 139 0000 5678", "(13900001111)",
            "138.0000.2222", "13900003333"),
  email = c("zhangsan@163.COM", " lisi@example.com  ",
            "wangwu@gmail.com", "zhaoliu@ qq.com", NA)
)

cat("=== Raw Data ===\n")
print(customers)

# 2. Clean Name
customers <- customers |>
  mutate(
    # Remove spaces + Capitalize the first letter(English Name)
    name_clean = str_trim(name) |>
      str_to_title() |>
      str_replace_all("\\s+", " ")  # Replace multiple spaces with a single space
  )

# 3. Delete a Phone Number(Remove spaces,-,.,+86,())
customers <- customers |>
  mutate(
    phone_clean = str_replace_all(phone, "[\\s\\-\\.\\(\\)\\+86]", ""),
    # Verification 11 Mobile phone number
    phone_valid = str_detect(phone_clean, "^1[3-9]\\d{9}$")
  )

# 4. Clean Up Your Inbox
customers <- customers |>
  mutate(
    email_clean = str_trim(email) |> str_to_lower(),
    # Verify the email address format
    email_valid = str_detect(email_clean, "^[\\w.+-]+@[\\w.-]+\\.[a-z]{2,}$")
  )

# 5. Output the cleaning results
cat("\n=== Data After Cleaning ===\n")
print(customers |> select(name_clean, phone_clean, phone_valid,
                          email_clean, email_valid))

# 6. Extracting Data Features
customers <- customers |>
  mutate(
    # Identify the mobile carrier based on a phone number
    operator = case_when(
      str_detect(phone_clean, "^1(3[0-9]|4[5-9]|5[0-35-9]|66|7[2-35-8]|8[0-9]|9[0-35-9])\\d{8}$") ~ "China Mobile",
      str_detect(phone_clean, "^1(3[0-2]|4[5-7]|5[3-5-7]|6[2567]|7[0-3]|8[0-3])\\d{8}$") ~ "China Unicom",
      str_detect(phone_clean, "^1(33|34|49|53|7[37]|8[0-2])\\d{8}$") ~ "China Telecom",
      TRUE ~ "Unknown"
    ),
    # Email Domain
    email_domain = str_extract(email_clean, "@[a-z0-9.]+"),
    # Before the phone number 3 bit
    phone_prefix = str_sub(phone_clean, 1, 3)
  )

cat("\n=== Data Characteristics ===\n")
print(customers |> select(name_clean, operator, phone_prefix, email_domain))

# 7. Text Statistics
cat("\n=== Distribution of Email Domain Names ===\n")
print(table(customers$email_domain))

cat("\n=== Distribution of Carriers ===\n")
print(table(customers$operator))

# 8. Identify invalid data
cat("\n=== Invalid data ===\n")
invalid <- customers |> filter(!phone_valid | !email_valid)
print(invalid |> select(name_clean, phone_clean, phone_valid,
                        email_clean, email_valid))
51 سطر من الكود المنطقي (تجاوز الحد 40, للعرض فقط)

النتائج المتوقعة (مقتطف):

TEXT 📖 للعرض فقط
=== Data After Cleaning ===
# A tibble: 5 × 6
  name_clean phone_clean   phone_valid email_clean         email_valid
  <chr>      <chr>         <lgl>       <chr>               <lgl>      
1 Alice       13800001234   TRUE        zhangsan@163.com    TRUE       
2 Bob       13900005678   TRUE        lisi@example.com    TRUE       
3 Wangwu     13900001111   TRUE        wangwu@gmail.com    TRUE       
4 Zhao Liu   13800002222   TRUE        zhaoliu@qq.com      TRUE       
5 Eve       13900003333   TRUE        <NA>                FALSE      

=== Distribution of Carriers ===
  China Telecom China Unicom China Mobile 
        1        2        2


❓ أسئلة شائعة

س كيف أختار بين stringr ووظائف سلسلة R الأساسية؟
ج استخدم stringr للمشاريع الجديدة
س كيف تُستخدم المؤشرات السالبة مع str_sub()؟
ج تبدأ الأرقام السالبة من النهاية. يستخرج str_sub(x, -3) الأحرف الثلاثة الأخيرة؛ بينما يستخرج str_sub(x, 1, -2) كل الأحرف من البداية وحتى الحرف قبل الأخير.
س كيف يمكنني استخراج الأرقام؟
ج str_extract_all(x, "\\d+") يستخرج جميع السلاسل الرقمية (قائمة). str_extract(x, "\\d+") يستخرج الرقم الأول (متجه).
س ماذا أفعل إذا ظهرت الأحرف الصينية كنص مشوه؟
ج يستخدم الإصدار R 4.x ترميز UTF-8 بشكل افتراضي، لذا لا ينبغي أن يظهر أي نص مشوه. إذا واجهت نصًّا مشوَّهًا، فاستخدم stringi::stri_encode() لتحويل الترميز، أو استخدم locale = locale(encoding = "GBK") عند قراءة الملف.
س ما الفرق بين str_c() وpaste()؟
ج إنهما متكافئان بشكل أساسي. ومع ذلك، فإن str_c() يوفر اتساقًا أفضل (حيث يقوم بنقل قيم NA بشكل افتراضي) ويكون أسهل في القراءة عند استخدامه مع الأنابيب.

📖 ملخص


📝 تمارين

  1. المسألة الأساسية: استخدم str_c() لربط المتجهين c("Apple", "Banana", "Cherry") وc(1, 2, 3)، وأخرج النتائج التالية: «التفاح 1 يوان»، «الموز 2 يوان»، و«الكرز 3 يوان».

  2. المسائل الأساسية: استخدم str_length() لحساب عدد الأحرف في "Hello World" و"Hello World" و"". استخدم str_sub() لاستخراج الأحرف من السابع إلى الحادي عشر من عبارة "Hello World".

  3. المشكلة الأساسية: استخدم str_detect() لتحديد العناصر في c("apple", "banana", "cherry") التي تنتهي بحرف «a»، ثم أخرج متجهًا منطقيًّا.

  4. تمرين متقدم: قم بتنظيف البيانات غير الصحيحة التالية: ① احذف المسافات من عناوين البريد الإلكتروني وحوّلها إلى أحرف صغيرة؛ ② استخرج نطاق البريد الإلكتروني؛ ③ تحقق من صحة تنسيق البريد الإلكتروني (@ + النطاق + . + حرفان على الأقل). استخدم mutate() لإضافة 3 أعمدة جديدة من البيانات.

  5. التحدي: قم بمحاكاة 100 سطر من بيانات العملاء (بما في ذلك أرقام هواتف وعناوين بريد إلكتروني وأسماء غير صالحة متنوعة) وأكمل عملية تنقية البيانات التالية: ① تنقية الأسماء ② تنقية أرقام الهواتف ③ التحقق من أرقام الهواتف ④ تنقية عناوين البريد الإلكتروني ⑤ استخراج معلومات شركة الاتصالات ⑥ حساب النسبة المئوية للبيانات غير الصالحة. اطبع إطارات البيانات قبل التنقية وبعدها، واحفظ لقطات شاشة لها.

Web-Tutorial.com

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

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

100%