-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathindex.Rmd
498 lines (338 loc) · 24.2 KB
/
index.Rmd
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
---
author:
- name: '[Gede Primahadi Wijaya Rajeg](https://udayananetworking.unud.ac.id/lecturer/880-gede-primahadi-wijaya-rajeg) <a itemprop="sameAs" content="https://orcid.org/0000-0002-2047-8621" href="https://orcid.org/0000-0002-2047-8621" target="orcid.widget" rel="noopener noreferrer" style="vertical-align:top;"><img src="https://orcid.org/sites/default/files/images/orcid_16x16.png" style="width:1em;margin-right:.5em;" alt="ORCID iD icon"></a>'
affiliation: "Program Studi [Sastra Inggris](https://twitter.com/sasingunud?lang=en) & *Centre for Interdisciplinary Research on the Humanities and Social Sciences* ([CIRHSS](http://www.cirhss.org)), [Fakultas Ilmu Budaya](https://fib.unud.ac.id), [Universitas Udayana](https://www.unud.ac.id)"
date: "*Created*: 1 April, 2022; *Last update*: `r format(Sys.time(), '%d %B, %Y')`"
title: "Pengolahan teks dasar dengan [R](https://www.r-project.org) menggunakan [stringr](https://stringr.tidyverse.org/index.html)"
output:
html_notebook:
fig_caption: yes
fig_width: 6
theme: "united"
highlight: "pygment"
number_sections: yes
toc: yes
toc_float: yes
code_folding: show
link-citations: yes
bibliography: "references.bib"
csl: unified_stylesheet_linguistics.csl
---
<style>
p.comment {
background-color: #E5FFCC;
padding: 10px;
border: 1px solid black;
margin-left: 25px;
border-radius: 5px;
}
</style>
<a rel="license" href="http://creativecommons.org/licenses/by-nc-sa/4.0/"><img alt="Creative Commons License" style="border-width:0" src="https://i.creativecommons.org/l/by-nc-sa/4.0/88x31.png" /></a> [](https://doi.org/10.17605/OSF.IO/9ZHDJ) <br /><i>The materials in this R Markdown Notebook are licensed under a <a rel="license" href="http://creativecommons.org/licenses/by-nc-sa/4.0/">Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License</a></i>.
# Pengantar {.unnumbered}
Materi pada R Markdown Notebook ini dibawakan pada [*R-Ladies Jakarta 15*^*th*^ *meetup*](https://udayananetworking.unud.ac.id/lecturer/gallery/photo/880-gede-primahadi-wijaya-rajeg/1318) (2 April 2022, 1400-1600 WIB) dengan tema *Basic text manipulation with `stringr`* [@rajeg_pengolahan_2022]. Jika materi ini digunakan kembali, menjadi dasar, ataupun dikutip untuk keperluan lokakarya dan hal-hal lainnya, mohon mengutip materi ini sebagai berikut:
> Rajeg, Gede Primahadi Wijaya. 2022. Pengolahan teks dasar dengan R menggunakan stringr. *Open Science Framework (OSF)*. doi: [10.17605/OSF.IO/9ZHDJ](https://doi.org/10.17605/OSF.IO/9ZHDJ). https://osf.io/9zhdj/ (2 April, 2022).
Dan juga salindia pembuka sebelum pelaksanaan lokakarya [@rajeg_basic_2022]:
> Rajeg, Gede Primahadi Wijaya. 2022. *Basic text manipulation with stringr*. OSF Preprints. doi: [10.31219/osf.io/q9yva](https://doi.org/10.31219/osf.io/q9yva). [https://osf.io/q9yva/](https://doi.org/10.31219/osf.io/q9yva) (2 April, 2022).
Pembaca disarankan mempelajari langsung dua sumber utama terkait `stringr`, yaitu (i) buku teks oleh Wickham dan Grolemund [-@wickham_r_2017], utamanya [Bab 14](https://r4ds.had.co.nz/strings.html), dan (ii) [*cheatsheet*](https://github.com/rstudio/cheatsheets/blob/main/strings.pdf) PDF untuk fungsi-fungsi kunci dalam `stringr`. Bacaan lain yang mungkin bisa dilihat adalah makalah kami [@rajeg_working_2018] yang salah satu bagiannya membahas pengolahan teks dasar menggunakan sejumlah fungsi pengolahan teks dari instalasi dasar R (bukan menggunakan `stringr`) (kode sumber makalah tersebut dapat diakses melalui [tautan berikut](https://doi.org/10.4225/03/5a7ee2ac84303) atau [berikut](https://osf.io/s6kh8/)).
# Persiapan
```{r setup}
# global option chunck
knitr::opts_chunk$set(echo = TRUE, include = TRUE, message = FALSE, warning = FALSE)
```
```
# install package stringr
install.packages("stringr")
```
Aktifkan modul/package `stringr`.
```{r aktifkan-modul-stringr}
# load the packages
library(stringr)
```
Muat data teks berupa kalimat dan kata-kata.
```{r muat-data-kalimat-stringr-semua}
eng_sentence_all <- scan(file = "data/eng_stringr_sentences_all.txt", what = "char", sep = "\n", quiet = TRUE)
length(eng_sentence_all) # ada 720 elemen kalimat
sample(eng_sentence_all, size = 3) # tampilkan 3 kalimat acak saja
```
```{r muat-data-ly, echo = FALSE, include = FALSE, eval = FALSE}
eng_sentence_ly <- scan(file = "data/eng_sentences_ly.txt", what = "char", sep = "\n", quiet = TRUE)
sample(eng_sentence_ly, size = 3)
```
```{r muat-data-ze, echo = FALSE, include = FALSE, eval = FALSE}
eng_sentence_ze <- scan(file = "data/eng_sentences_ze.txt", what = "char", sep = "\n", quiet = TRUE)
sample(eng_sentence_ze, size = 3)
```
```{r muat-data-kata}
words <- stringr::words # data kata (*words*) dari package stringr
sample(words, size = 3)
```
```{r muat-data-nama-buah}
fruits <- stringr::fruit # data kata-kata nama buah (*fruits*) dari package stringr
sample(fruits, size = 3)
```
# Pencarian dan pendeteksian (rangkaian) karakter
## Menguji pola pencarian dan hasil yang ditangkap dengan `str_view_all()`
Fungsi `str_view_all()` memerlukan kita menginstall package `htmlwidgets`. Jika tidak, error akan muncul seperti pada gambar di bawah ini.
```{r error-html-widget, echo = FALSE}
knitr::include_graphics("htmlwidget-error.png")
```
```{r install-htmlwidgets, eval = FALSE}
# install htmlwidgets package
install.packages("htmlwidgets")
```
Kode berikut mencoba menampilkan keberadaan rangkaian karakater `"ze"` dalam vektor teks `eng_sentence_all`.
```{r melihat-hasil-pencarian, message = FALSE, warning = FALSE}
str_view_all(string = eng_sentence_all, pattern = "ze", match = TRUE)
```
### Latihan {.unnumbered}
1. Ubah parameter argumen `match = TRUE` menjadi `match = FALSE`, lalu jalankan kode sebelumnya dengan pola pencarian `"ze"`. Apa yang terjadi pada luarannya? Apa fungsi dari `match = FALSE`?
2. Gunakan `str_view_all()` untuk menampilkan rangkaian karakter `"ly"` pada vektor teks `eng_sentence_all`.
3. Bagaimana pola pencarian untuk menampilkan rangkaian karakter `"ly"` yang diikuti dengan spasi (*whitespace*)?
## Mendeteksi keberadaan pola rangkaian karakter dengan `str_detect()`
Fungsi `str_detect()` menghasilkan luaran logis `TRUE` dan `FALSE` yang menyatakan apakah rangkaian karakter yang kita cari ditemukan (`TRUE`) atau tidak (`FALSE`) pada suatu vektor teks/karakter.
```{r deteksi-pola-pencarian}
# buat 50 sampel kalimat sederhana
eng_sentence_all_sample <- sample(x = eng_sentence_all, size = 50)
# apakah rangkaian karakter "ed" ditemukan dalam `eng_sentence_all_sample`?
str_detect(string = eng_sentence_all_sample, pattern = "ed")
```
### Latihan {.unnumbered}
1. Gunakan `str_view_all()` untuk menampilkan rangkaian karakter `"ed"` pada vektor teks `eng_sentence_all_sample`.
2. Apakah rangkaian karakter konsonan `"ck"` ditemukan dalam nama-nama buah pada vektor teks `fruits`?
- Jika ya, gunakan `str_view_all()` untuk menampilkan nama buah apa yang mengandung rangkaian karakter konsonan `"ck"` pada vektor teks `fruits`.
------------------------------------------------------------------------
Fungsi `str_detect()` juga dapat digunakan untuk menyaring observasi yang diinginkan dalam tabel (*data frame*) berdasarkan rangkaian karakter tertentu. Ini dimungkinkan karena luaran `str_detect()` berupa struktur logis `TRUE` dan `FALSE` yang menjadi landasan dalam menyaring observasi, salah satunya dalam tabel.
```{r muat-data-tabel}
# muat data tabel hanya kolom 4 - 7
verbs_idn <- read.table(file = "data/verb_semantics.txt", header = TRUE, sep = "\t")[4:7]
# lihat enam baris pertama
head(verbs_idn)
```
Kode berikut menyaring observasi (`subset()`) dalam tabel data `verbs_idn` berdasarkan apakah kolom `example_target` mengandung teks (yaitu kata kerja *ber-*) dengan rangkaian karakter `"da"` [lihat @primahadi_metonymy_2013 untuk makalah yang dilandasi atas data tabel tersebut].
```{r saring-observasi}
subset(verbs_idn, str_detect(string = example_target, pattern = "da"))
```
### Latihan {.unnumbered}
1. Ubah kode sebelumnya untuk menyaring/mendeteksi kata-kata dalam kolom **`example_source`** yang mengandung rangkaian karakter `"ar"`.
## Menyaring elemen vektor teks yang mengandung rangkaian karakter tertentu dengan `str_subset()`
Berbeda dengan `str_detect()`, yang mengeluarkan `TRUE` dan `FALSE`, `str_subset()` (i) mendeteksi *dan* (ii) mengeluarkan elemen dalam vektor teks yang mengandung rangkaian karakter yang dicari.
```{r saring-kalimat-dengan-karakter-ing}
str_subset(string = eng_sentence_all_sample, pattern = "ing")
```
Tentu kita bisa simpan hasil penyaringan ini ke vektor lain.
```{r saring-kalimat-dengan-karakter-ing-simpan}
# simpan luaran kode berikut ke vektor `ing_output`
ing_output <- str_subset(string = eng_sentence_all_sample, pattern = "ing")
ing_output
```
### Latihan {.unnumbered}
1. Buah apa yang namanya mengandung karakter `"ck"`? Gunakan `str_subset()` pada vektor teks `fruits` untuk menjawab pertanyaan ini.
1. Gunakan `str_subset()` untuk menyaring kalimat dalam vektor `eng_sentence_all` yang mengandung rangkaian karakter `"who"`. Apakah pola pencarian `"who"` ini mengeluarkan kalimat yang mengandung kata *who* 'siapa' dalam bahasa Inggris?
---------
<p class="comment">**Catatan tentang _regular expressions_**<br><br/><i>[Regular expressions](https://www.regular-expressions.info/tutorial.html)</i> (RegEx) adalah pola pencarian karakter yang lebih canggih dan fleksibel yang perlu dipelajari untuk pengolahan dan manipulasi teks tingkat lanjut [lihat @wickham_r_2017, sub-bagian 14.3 untuk ulasan lebih rinci].<br/><br/> Salah satu jenis ReGex yang penting diketahui adalah **pewatas rangkaian karakter yang mencerminkan kata** (*word boundary*) (`"\\b"`). Untuk kasus pencarian rangkaian karakter `"who"` sebelumnya, kita melakukan pencarian dengan rangkaian karakter tanpa RegEx karena kita tidak memperinci bahwa karakter `"who"` yang kita inginkan adalah kata _who_ bukannya rangkaian karakter `"who"` yang bisa muncul dalam kata _**who**le_, _**who**ever_, dll. Untuk itu, pola pencarian kita untuk "kata" _who_ (bukan rangkaian karakter `"who"`) haruslah lebih spesifik dan karakter RegEx pewatas kata (`"\\b"`) dapat membantu dalam hal ini, yaitu `"\\bwho\\b"`.</p>
Bandingkan luaran kedua baris kode berikut untuk pola pencarian dengan dan tanpa RegEx pewatas kata (`"\\b"`):
```{r literal-search}
# tanpa regex pewatas kata "\\b" di kedua sisi karakter yang dicari
str_subset(string = eng_sentence_all, pattern = "who")
# tanpa regex pewatas kata "\\b" di kedua sisi karakter yang dicari
str_view_all(string = eng_sentence_all, pattern = "who", match = TRUE)
```
```{r word-boundary-search}
# dengan regex pewatas kata "\\b" di kedua sisi karakter yang dicari
str_subset(string = eng_sentence_all, pattern = "\\bwho\\b")
# dengan regex pewatas kata "\\b" di kedua sisi karakter yang dicari
str_view_all(string = eng_sentence_all, pattern = "\\bwho\\b", match = TRUE)
```
### Latihan {-}
1. Gunakan RegEx pewatas kata (`"\\b"`) dengan `str_subset()` untuk menyaring kalimat dalam vektor `eng_sentence_all` yang mengandung kata-kata yang **diakhiri** dengan rangkaian karakter `"ing"` (misalnya, kata-kata seperti _text**ing**_, _liv**ing**_, _r**ing**_, _spr**ing**_, dll.)
1. Gunakan `str_subset()` dan pola pencarian dengan RegEx pewatas kata (`"\\b"`) untuk mengeluarkan kata-kata yang **diawali** dengan karakter `"ch"` (misalnya _**ch**ance_, _**ch**ap_, dll.) dalam vektor teks `words`.
------
<p class="comment">**Catatan tentang _regular expressions_**<br><br/>Selain pewatas rangkaian karakter berupa kata, terdapat dua lagi ReGex pewatas rangkaian karakter yang penting diketahui, yaitu **pewatas rangkaian karakter** secara umum (*anchor character*): (i) pewatas **posisi awal** rangkaian karakter (`"^"`) dan (ii) pewatas **posisi akhir** rangkaian karakter (`"$"`).</p>
Perhatikan kode berikut sebagai contoh penggunaan RegEx pewatas awal dan akhir rangkaian karakter [dikutip dari @wickham_r_2017, 202]:
```{r end-of-string}
# buat data sederhana
fruit_mini <- c("apple", "banana", "pear")
# menangkap karakter `"a"` yang muncul di akhir (`"$"`) rangkaian karakter nama buah pada vektor `fruit_mini`
str_view_all(string = fruit_mini, pattern = "a$")
str_subset(string = fruit_mini, pattern = "a$")
```
```{r beginning-of-string}
# menangkap karakter `"a"` yang muncul di akhir (`"$"`) rangkaian karakter nama buah pada vektor `fruit_mini`
str_view_all(string = fruit_mini, pattern = "^a")
str_subset(string = fruit_mini, pattern = "^a")
```
Kita bisa menggabungkan `"^"` dan `"$"` untuk mempertegas bahwa kita hanya ingin menangkap rangkaian karakter secara utuh. Bandingkan kedua kode berikut [dikutip dari @wickham_r_2017, 202]:
```{r partial-match}
# buat data lain
fruit_cake <- c("apple pie", "apple", "apple cake")
# pencarian sederhana (tanpa RegEx) untuk menangkap rangkaian karakter `"apple"`
str_view_all(string = fruit_cake, pattern = "apple")
str_subset(string = fruit_cake, pattern = "apple")
```
```{r complete-match}
# menangkap hanya rangkaian karakter utuh dari awal hingga akhir rangkaian karakter
str_view_all(string = fruit_cake, pattern = "^apple$")
str_subset(string = fruit_cake, pattern = "^apple$")
```
### Latihan {-}
1. Buah apa saja yang namanya **diawali** dengan karakter konsonan `"b"`? Gunakan `str_subset()` untuk mengeluarkan dari vektor `fruits` nama-nama buah yang diawali dengan karakter `"b"`.
1. Ada berapa buah yang namanya **berakhir** dengan karakter vokal `"o"`? Gunakan `str_subset()` untuk mengeluarkan dari vektor `fruits` nama-nama buah yang diawali dengan karakter `"o"`.
<p class="comment">**Tips**<br><br/>`stringr` juga memiliki dua fungsi khusus untuk mendeteksi keberadaan (rangkaian) karakter yang muncul (i) **di awal** rangkaian karakter, yaitu fungsi [`str_starts()`](https://stringr.tidyverse.org/reference/str_starts.html), dan (ii) **di akhir** rangkaian karakter, yaitu fungsi [`str_ends()`](https://stringr.tidyverse.org/reference/str_starts.html). Layaknya `str_detect()`, kedua fungsi ini mengeluarkan vektor logis `TRUE` dan `FALSE`.<br/><br/>Misalnya, `str_starts(fruit_mini, "p")` akan mendeteksi adakah elemen teks dalam vektor `fruit_mini` yang diawali dengan karakter `"p"`, tanpa perlu menggunakan RegEx pewatas karakter awal `"^"`. Sebaliknya, `str_ends(fruit_mini, "p")` akan mendeteksi keberadaan teks dalam `fruit_mini` yang diakhiri dengan karakter `"p"`, tanpa perlu menggunakan RegEx pewatas karakter akhir `"$"`.<br/><br/>RegEx tetap diperlukan jika menggunakan fungsi `str_subset()` untuk menyaring teks yang diawali atau diakhiri dengan (rangkaian) karakter tertentu.</p>
------
# Mengeluarkan (*extract*) pola karakter dari dalam teks
Fungsi `str_extract_all()` digunakan untuk "mengeluarkan" (*extract*) pola yang ditangkap dari pencarian karakter yang kita rancang. Sebagai contoh, vektor kalimat `eng_sentence_all` terdapat sejumlah nama-nama warna bahasa Inggris dan kita hanya ingin mengeluarkan kata-kata yang mencerminkan nama warna tersebut (tidak kata-kata lainnya dalam kalimat). Kita memerlukan karakter RegEx bernama "alternatif" (`|`) yang berarti 'atau'. Jika kita ingin mencari warna `"x"` **atau** `"y"` **atau** `"z"`, maka pola pencarian kita adalah `"(x|y|z)"`.
Pertama kita rampingkan data kalimat `eng_sentence_all` dengan menyaring hanya kalimat-kalimat yang mengandung nama-nama warna.
```{r ekstraksipertama}
# buat vektor karakter untuk regex pencarian dengan teknik "alternatif"
colour_pattern <- "(blue|orange|yellow|green|purple)"
# deteksi dan saring terlebih dahulu hanya kalimat yang berisi nama-nama warna "biru", "oranye", "kuning", "hijau", dan "ungu".
sent_colour <- str_subset(string = eng_sentence_all, pattern = colour_pattern)
# cari tahu berapa kalimat yang mengandung nama-nama warna
length(sent_colour) # 20 kalimat mengandung nama-nama warna tersebut
```
Baru kita keluarkan kata-kata nama warna dari vektor karakter `sent_colour` dan simpan luarannya ke vektor karakter lainnya dengan nama `word_colour`.
```{r ekstraksikedua}
# keluarkan nama-nama warna dari vektor `sent_colour` dan simpan ke vektor `word_colour`
word_colour <- str_extract_all(string = sent_colour, pattern = colour_pattern)
# lihat enam elemen pertama
head(word_colour) # luaran berupa List bukan Vektor karakter (atomis)
```
```{r ekstraksiketiga}
word_colour_vector <- unlist(word_colour) # unlist menjadi vektor karakter
word_colour_vector
```
Gunakan `str_sort()` untuk mengurutkan karakter secara alfabetis.
```{r menyortir-teks-secara-alfabetis}
str_sort(word_colour_vector)
```
Kita bisa gunakan `table()` untuk mentabulasi karakter vektor nama warna untuk mengetahui distribusi/frekuensi kemunculan warna tersebut.
```{r tabulasi-warna}
table(word_colour_vector)
```
```{r sortir-tabulasi}
# sortir nama warna dari frekuensi tertinggi ke terendah
word_colour_count <- table(word_colour_vector)
word_colour_count <- sort(word_colour_count, decreasing = TRUE)
word_colour_count
```
# Memecah teks menjadi unit yang lebih kecil
Fungsi `str_split()` digunakan untuk memecah teks berdasarkan pada karakter mana teks tersebut dipecah. Contoh paling sederhana adalah memecah kalimat menjadi kata dengan memecahnya pada karakter spasi (yang merupakan pemisah kata untuk karakter Roman yang dipahami oleh komputer).
```{r pecah-teks}
# contoh sederhana pemecahan kalimat -> kata dengan dua kalimat
two_sentences <- eng_sentence_all_sample[1:2]
# pecah teks pada karakter spasi `" "`.
str_split(two_sentences, pattern = " ") # luarannya adalah List
```
Isunya adalah tanda baca seperti titik (`.`) masih menempel pada kata yang mengakhiri kalimat. Pada situasi inilah kekuatan dari RegEx menjadi penting.
Kita perlu merancang pola pencarian RegEx yang menyatakan bahwa kita ingin memisahkan/memecah teks pada kelompok karakter **selain** kelompok karakter pembentuk kata, yaitu kelompok karakter **di luar** karakter alfanumeris dan strip `"-"`. Dalam konteks bahasa Inggris, `"-"` dipertahankan untuk menangkap kata seperti *computer-readable* sebagai satu unit, bukannya menjadi dua unit *computer* dan *readable*.
RegEx yang bisa digunakan adalah `"[^a-zA-Z0-9-]+"`, yang artinya: satu atau lebih (`"+"`) kelompok karakter (`"[...]"`) yang bukan (`"^"`) (i) alfanumeris kapital dan kecil (`"a-zA-Z0-9"`) dan strip (`"-"`).
```{r pecah-teks-regex}
# pecah teks pada karakter non-alfanumeris dan spasi `" "`.
str_split(two_sentences, pattern = "[^a-zA-Z0-9-]+")
```
Tentu luaran List ini bisa kita ubah menjadi vektor atomis:
```{r unlist-luaran-str-split}
split_sentence <- str_split(two_sentences, pattern = "[^a-zA-Z0-9-]+")
unlist(split_sentence)
```
Pemecahan teks dari kalimat menjadi kata ini dapat dilihat dari dua perspektif:
i. **memecah** (yaitu **memisahkan** dengan **menghilangkan**) karakter **selain** alfanumeris dan strip, menggunakan `str_split()`, atau
i. **menarik** (yaitu **mengeluarkan**/**mengekstraksi**) karakter yang membangun suatu kata, yaitu karakter alfanumeris dan strip, menggunakan `str_extract_all()`.
Jika kita mengambil perspektif kedua (dengan `str_extract_all()`), maka RegEx yang digunakan sedikit berbeda, yaitu dengan menghilangkan tanda negasi ('bukan') `"^"` dalam RegEx-nya. Perhatikan kode berikut dan bandingkan dengan teliti luaran `str_extract_all()` dengan luaran `str_split()` sebelumnya.
```{r ekstrak-kata}
# perspektif kedua memecah kalimat menjadi kata
# dengan **mengkekstraksi** kata-kata
str_extract_all(two_sentences, pattern = "[a-zA-Z0-9-]+")
```
Yang membedakan luaran `str_split()` dan `str_extract_all()` di atas, khususnya dalam konteks memecah teks kalimat menjadi kata adalah:
i. luaran `str_split()` menandai penghilangan/pemecahan tanda baca, dalam hal ini titik, dengan karakter kosong (lihat karakter `""` setelah kata `"ends"` dan `"enough"`).
i. luaran `str_extract_all()` hanya akan mengeluarkan/mengekstraksi karakter yang dinyatakan dalam pola pencariannya, yaitu satu atau lebih karakter alfanumeris dan strip; tidak ada karakter kosong yang mencerminkan dalam hal ini tanda titik.
Kita yang menentukan fungsi dan luaran seperti apa yang diinginkan.
# Mengubah komponen teks
## Mengubah karakter menjadi huruf besar atau kecil
Fungsi `str_to_upper()` mengubah karakter menjadi huruf kapital dan `str_to_lower()` menjadi huruf kecil.
```{r upper-case}
# mengubah nama warna sebelumnya menjadi huruf kapital
word_colour_caps <- str_to_upper(string = word_colour_vector)
word_colour_caps
```
```{r lower-case}
# mengubah nama warna kapital menjadi huruf kecil
str_to_lower(string = word_colour_caps)
```
### Latihan {-}
1. Lihat isi vektor `two_sentences` pada konsol dan perhatikan bentuk rangkaian karakternya. Kemudian jalankan fungsi `str_to_title()` dengan input `two_sentences`. Perubahan apa yang terjadi dan apa yang dilakukan oleh `str_to_title()`?
## Mengganti komponen teks dengan karakter lain
Terkadang kita perlu mengubah komponen teks tertentu layaknya fungsi *find and replace* pada peranti seperti MS Word. Dalam stringr, kita bisa menggunakan `str_replace()` dan `str_replace_all()`.
Varian dasar **tanpa** `..._all()`, yaitu `str_replace()`, hanya akan mengganti karakter yang **pertama kali** ditangkap oleh pola pencariannya, sedangkan karakter yang sama yang muncul setelahnya tidak akan ditangkap dan diganti.
Perhatikan kode berikut yang mencoba mengganti karakter `"e"` pada vektor `fruit_cake`.
```{r}
# lihat kembali vektor `fruit_cake`
fruit_cake
```
```{r mengganti-sederhana}
# gunakan str_replace() untuk mengganti karakter `"e"` yang ditemukan pertama dengan strip `"-"`
str_replace(string = fruit_cake, pattern = "e", replacement = "-")
```
```{r mengganti-semua}
# gunakan str_replace_all() untuk mengganti SEMUA karakter `"e"` dengan strip `"-"`
str_replace_all(string = fruit_cake, pattern = "e", replacement = "-")
```
### Latihan {-}
1. Ganti rangkaian karakter untuk kata `"apple"` pada vektor `fruit_cake` (yang berisi `"apple pie"`, `"apple"`, dan `"apple cake"`) dengan kata `"butter"`.
# Menggabungkan vektor rangkaian karakter
Untuk menggabungkan dua atau lebih rangkaian karakter, gunakan `str_c()`.
```{r gabung-sederhana}
# menggabungkan dua rangkaian karakter: "ba" dan "li"
str_c("ba", "li")
```
```{r gabung-sederhana-1}
karakter_1 <- c("b", "l", "k")
karakter_2 <- c("a", "i", "u")
# gabungkan tiga karakter dari dua vektor
str_c(karakter_1, karakter_2)
```
```{r gabung-sederhana-2}
# gabungkan dan apit tiga karakter dalam satu vektor dengan dua karakter lain yaitu "<m>"
str_c("<m>", karakter_1, "<m>")
```
Jika salah satu dari dua vektor karakter yang akan digabung memiliki jumlah elemen yang lebih sedikit, maka elemen pada vektor tersebut akan digunakan ulang. Perhatikan contoh berikut.
```{r gabung-beda-ukuran}
two_word_fruit <- c("apple", "banana")
four_word_snack <- c("cake", "juice", "pie", "chocolate")
# gabungkan kedua vektor di atas
str_c(two_word_fruit, four_word_snack, sep = "_")
```
Gunakan argumen `sep = ...` untuk mengatur pemisah di antara rangkaian karakter yang digabungkan. Secara bawaan, argumen `sep = ...` telah diatur menjadi `sep = ""`.
```{r gabung-separator}
# atur pemisah di antara karakter yang digabungkan dengan `sep = ...`
str_c(karakter_1, karakter_2, sep = "_")
```
Argumen `collapse = ...` akan menyatukan sejumlah rangkaian karakter menjadi **satu** rangkaian karakter. Bandingkan kedua kode berikut yang menggunakan `sep = ...` dan `collapse = ...`:
```{r separated-combination}
# dengan sep = ..., penggabungan berikut menghasilkan tiga elemen rangkaian karakter
three_strings <- str_c("<m>", karakter_1, "<m>", sep = "_")
three_strings
# Hitung jumlah elemen dalam vektor `three_strings`
length(three_strings)
```
```{r collapse}
# dengan collapse = ..., penggabungan berikut menghasilkan satu elemen rangkaian karakter
one_string <- str_c("<m>", karakter_1, "<m>", collapse = "_")
one_string
# Hitung jumlah elemen dalam vektor `one_string`
length(one_string)
```
# Menyimpan vektor karakter ke dalam berkas teks (*plain text*)
Gunakan fungsi `cat()` yang tersedia dari instalasi dasar R untuk menyimpan vektor karakter ke dalam berkas teks sederhana (*plain text* dengan ekstensi `.txt`).
```{r saving-character-vector}
# simpan vektor nama warna ke berkas `"selected-colours.txt"`
# dalam direktori `results`
# yang masing-masing elemen vektornya dipisahkan dengan baris baru (`sep="\n"`)
cat(word_colour_vector, file = "results/selected-colours.txt", sep = "\n")
```
# *Session info* {-}
```{r sessinfo}
devtools::session_info()
```
# Daftar acuan {-}