Rでの文字列処理:`stringr`の完全ガイド
実際のプロジェクトでは、データクレンジングにかかる時間の80%が文字列処理に費やされています。具体的には、電話番号の整形、メールアドレスの抽出、キーワードの置換、文字列の分割や連結などです。Rの
stringrパッケージはtidyverseによって公式に推奨されており、標準のRパッケージであるgrep/gsubよりも一貫性が高く、使いやすいです。
このレッスンを修了すると、電話番号の検証、メールアドレスの抽出、テキストのセグメンテーション、URLの解析など、あらゆるテキストのクリーニング作業をRを使って行うことができるようになります。
1. 学習内容
- 文字列の基礎(作成、連結、長さ、結合)
- stringr の 5 つの主要関数(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の数式を使って手動で調整する場合、30分かかりますが、Pythonのreモジュールを使えば、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}$")
たった3行のコードで5つのクリーニングタスクを完了。
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) は最後の 3 文字を取得し、str_sub(x, 1, -2) は先頭から最後から 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」の 7 文字目から 11 文字目までを抽出してください。 -
基本問題:
str_detect()を用いて、c("apple", "banana", "cherry")の中で「a」で終わる要素を特定し、論理ベクトルを出力せよ。 -
応用演習:以下の不適切なデータを修正してください。① メールアドレスからスペースを削除し、小文字に変換する。② メールアドレスのドメインを抽出する。③ メールアドレスの形式(
@+ ドメイン +.+ 2文字以上)が正しいか検証する。mutate()を使用して、3つの新しいデータ列を追加してください。 -
課題:100行分の顧客データ(さまざまな無効な電話番号、メールアドレス、氏名を含む)をシミュレートし、以下のデータクレンジング処理を実行してください:① 氏名のクレンジング ② 電話番号のクレンジング ③ 電話番号の検証 ④ メールアドレスのクレンジング ⑤ 通信事業者の情報の抽出 ⑥ 無効なデータの割合の算出。クレンジング前後のデータフレームを印刷し、そのスクリーンショットを保存してください。



