R: معالجة سلاسل R: دليل شامل لمكتبة `stringr`
آخر تحديث: 2026-08-26
في المشاريع العملية، يُنفق 80% من وقت تنقية البيانات على معالجة السلاسل — تنقية أرقام الهواتف، واستخراج عناوين البريد الإلكتروني، واستبدال الكلمات المفتاحية، وتقسيم السلاسل وربطها. يُوصى رسميًا باستخدام حزمة
stringrفي لغة R من قِبل tidyverse؛ فهي أكثر اتساقًا وأسهل في الاستخدام مقارنةً بحزمةgrep/gsubالقياسية في لغة R.
بعد الانتهاء من هذا الدرس، ستتمكن من استخدام لغة R لتنفيذ أي مهمة تتعلق بتنقية النصوص: التحقق من صحة أرقام الهواتف، واستخراج عناوين البريد الإلكتروني، وتقسيم النصوص، وتحليل عناوين URL.
1. ما ستتعلمه
- أساسيات السلاسل (الإنشاء، التسلسل، الطول، الربط)
- الوظائف الأساسية الخمس لـ stringr (str_c/str_sub/str_detect/str_replace/str_split)
- str_trim/str_pad: معالجة المسافات البيضاء
- عمليات تحويل سلاسل الأحرف إلى متجهات
- ترميز الأحرف (UTF-8 مقابل GBK)
- تجربة عملية: تنقية أرقام الهواتف وعناوين البريد الإلكتروني والعناوين
2. قصة عن تنقية البيانات
(1) المشكلة: البيانات غير الدقيقة
بعد تلقي مجموعة من بيانات العملاء، اكتشف تشين ما يلي:
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
يجب تنظيفه حتى:
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
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 أسطر فقط من التعليمات البرمجية.
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) إنشاء سلاسل نصية
# 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() — التسلسل
# 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 وظائف رئيسية
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()
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() الطول
# 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(): استخراج جزء من السلسلة
# 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()
# 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()
# 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() المسافات البيضاء
# 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() — ملء الفراغات
# 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_* تجاه الأحرف الكبيرة والصغيرة
# 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() اقتطاع
# Truncate excessively long strings(add ...)
str_trunc("This is a very long sentence.", width = 10)
# [1] "This is..."
6. تقسيم السلسلة باستخدام str_split()
# 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. تمرين عملي: تنظيف بيانات العملاء
فيما يلي مثال على مسار عمل كامل يجمع بين جميع مفاهيم السلاسل التي تم تناولها في هذا الدرس.
▶ مثال: التنظيف الشامل لبيانات العملاء
# ============================================
# 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))
النتائج المتوقعة (مقتطف):
=== 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+") يستخرج الرقم الأول (متجه).stringi::stri_encode() لتحويل الترميز، أو استخدم locale = locale(encoding = "GBK") عند قراءة الملف.str_c() وpaste()؟str_c() يوفر اتساقًا أفضل (حيث يقوم بنقل قيم NA بشكل افتراضي) ويكون أسهل في القراءة عند استخدامه مع الأنابيب.📖 ملخص
- يُعد «stringr» المعيار القياسي في «tidyverse» لمعالجة السلاسل النصية؛ وهو أكثر اتساقًا وأسهل في الاستخدام من وظائف السلاسل النصية الأساسية في لغة R
- 5 وظائف أساسية:
str_cالتسلسل /str_subالسلسلة الفرعية /str_detectالكشف /str_replace(_all)الاستبدال /str_splitالتقسيم - وظائف المساعدة:
str_lengthالطول /str_trimإزالة المسافات /str_padملء الفراغات /str_to_*تحويل حالة الأحرف - تعالج جميع دوال stringr القيم NA تلقائيًا (دون إصدار أخطاء) — وهي أكثر سهولة في الاستخدام مقارنة بـ R الأساسي
str_c()القيمة الافتراضية هيsep = ""(بدون فاصل)؛ استخدم مسافة لتحديدsep = " "صراحةًstr_replace()استبدال الأول،str_replace_all()استبدال الكل- غالبًا ما تُستخدم معالجة السلاسل جنبًا إلى جنب مع التعبيرات النمطية (
\\d+للأرقام، و\\s+للمسافات البيضاء، و^...$لنقاط البداية والنهاية) — وسنتناول هذا الموضوع بمزيد من التفصيل في الدرس التالي.
📝 تمارين
-
المسألة الأساسية: استخدم
str_c()لربط المتجهينc("Apple", "Banana", "Cherry")وc(1, 2, 3)، وأخرج النتائج التالية: «التفاح 1 يوان»، «الموز 2 يوان»، و«الكرز 3 يوان». -
المسائل الأساسية: استخدم
str_length()لحساب عدد الأحرف في"Hello World"و"Hello World"و"". استخدمstr_sub()لاستخراج الأحرف من السابع إلى الحادي عشر من عبارة "Hello World". -
المشكلة الأساسية: استخدم
str_detect()لتحديد العناصر فيc("apple", "banana", "cherry")التي تنتهي بحرف «a»، ثم أخرج متجهًا منطقيًّا. -
تمرين متقدم: قم بتنظيف البيانات غير الصحيحة التالية: ① احذف المسافات من عناوين البريد الإلكتروني وحوّلها إلى أحرف صغيرة؛ ② استخرج نطاق البريد الإلكتروني؛ ③ تحقق من صحة تنسيق البريد الإلكتروني (
@+ النطاق +.+ حرفان على الأقل). استخدمmutate()لإضافة 3 أعمدة جديدة من البيانات. -
التحدي: قم بمحاكاة 100 سطر من بيانات العملاء (بما في ذلك أرقام هواتف وعناوين بريد إلكتروني وأسماء غير صالحة متنوعة) وأكمل عملية تنقية البيانات التالية: ① تنقية الأسماء ② تنقية أرقام الهواتف ③ التحقق من أرقام الهواتف ④ تنقية عناوين البريد الإلكتروني ⑤ استخراج معلومات شركة الاتصالات ⑥ حساب النسبة المئوية للبيانات غير الصالحة. اطبع إطارات البيانات قبل التنقية وبعدها، واحفظ لقطات شاشة لها.