Menu

Napisy (stringi) w R: paste, sprintf, gsub, substr i nie tylko

Wszystko, czego potrzebujesz do pracy z tekstem w R: tworzenie napisów, łączenie przez paste i paste0, formatowanie przez sprintf oraz wyszukiwanie przez gsub, grepl i strsplit.

Na tej stronie są działające edytory: edytuj, uruchamiaj i od razu zobacz wynik.

Tworzenie napisów w R

Napis w R to tekst w cudzysłowie. Działają zarówno cudzysłowy podwójne, jak i pojedyncze, i znaczą dokładnie to samo. Konwencja to cudzysłowy podwójne, a pojedyncze stosuje się wtedy, gdy sam tekst zawiera cudzysłów podwójny:

Sekwencje z ukośnikiem odwrotnym działają jak w większości języków: \" dla dosłownego cudzysłowu, \n dla nowej linii, \t dla tabulatora, \\ dla samego ukośnika odwrotnego.

A teraz błąd, który każdy początkujący w R popełnia dokładnie raz: pytanie napisu o długość przez length().

nchar() liczy znaki, czyli 5. length() liczy elementy wektora, a pojedynczy napis to wektor z jednym elementem, więc wynik to 1. W R wszystko jest wektorem, także tekst, a wszystkie funkcje z tej strony po cichu działają element po elemencie na całych wektorach tekstowych. To zaleta, gdy już przestanie cię zaskakiwać.

Łączenie napisów: paste() i paste0()

R nie ma + dla napisów. Do łączenia służy paste(), która domyślnie łączy argumenty spacją, i paste0(), która łączy je bez niczego:

Ponieważ paste jest wektorowa, przekazanie jej wektora buduje wiele napisów naraz. Tak w jednej linii generuje się nazwy plików, etykiety i identyfikatory:

A argument collapse robi coś odwrotnego: skleja cały wektor w jeden napis z wybranym separatorem:

Zapamiętaj podział: sep określa klej między argumentami, a collapse klej między elementami jednego wektora. Możesz użyć obu w jednym wywołaniu.

Formatowanie przez sprintf()

Gdy potrzebujesz liczb sformatowanych w tekście (stała liczba miejsc po przecinku, wyrównana szerokość), paste() przestaje wystarczać i do akcji wchodzi sprintf(). Używa kodów formatu w stylu C: %s dla napisów, %d dla liczb całkowitych, %f dla liczb dziesiętnych:

%.1f oznacza „jedno miejsce po przecinku”, %.3f trzy, a %05d dopełnia zerami do pięciu cyfr. Podwójne %% daje dosłowny znak procentu. sprintf() też jest wektorowa, więc potrafi sformatować całą kolumnę wartości jednym wywołaniem. Wzorzec raportowania sprintf() + cat() opisuje artykuł o wejściu i wyjściu.

Zmiana wielkości liter i wycinanie: toupper(), tolower(), substr()

Zmiana wielkości liter robi dokładnie to, co mówi nazwa:

tolower() najbardziej przydaje się przy normalizowaniu chaotycznych danych przed porównaniem: "Yes", "YES" i "yes" stają się tą samą wartością.

substr(x, start, stop) wycina fragment według pozycji znaków, licząc od 1 (R wszędzie indeksuje od 1):

Oba końce są włączone: pozycje od 1 do 11 dają "Programming".

Wyszukiwanie i zamiana: sub(), gsub() i grepl()

sub() zamienia pierwsze wystąpienie wzorca; gsub() („global substitute”) zamienia wszystkie:

Jeden kluczowy szczegół: wzorzec jest domyślnie wyrażeniem regularnym, a nie dosłownym tekstem. Znaki regex, takie jak ., *, ( i ?, mają specjalne znaczenie: goła . pasuje do dowolnego znaku. Gdy chodzi ci o dosłowny tekst, przekaż fixed = TRUE:

Pierwsza linia daje a-b-c; druga daje -----, bo jako regex . dopasowała każdy pojedynczy znak. Dopóki nie poznasz wyrażeń regularnych, niech fixed = TRUE będzie twoim domyślnym wyborem, a nic cię nie ugryzie.

grepl() niczego nie zamienia: sprawdza, czy każdy element pasuje, i zwraca wektor logiczny. Dzięki temu to standardowe narzędzie do filtrowania tekstu:

Pierwszy wynik oznacza, które nazwy plików zawierają .csv; drugi używa tego wektora logicznego, żeby zostawić tylko dopasowania.

Dzielenie i przycinanie: strsplit() i trimws()

strsplit() tnie napis według separatora. Ma jedną osobliwość: zwraca listę, bo potrafi podzielić wiele napisów naraz. Przy pojedynczym napisie weź pierwszy element przez [[1]]:

A trimws() usuwa białe znaki, w które prawdziwe dane zawsze są owinięte:

Domyślnie przycina oba końce; which = "left" albo "right" przycina tylko jedną stronę (nazwy odnoszą się do początku i końca napisu).

Alternatywa: stringr

Wszystko powyżej to bazowy R: zawsze dostępny, bez instalacji. Pakiet stringr z tidyverse opakowuje te same operacje w spójny schemat nazw str_*, w którym napis jest zawsze pierwszym argumentem, co wielu osobom łatwiej zapamiętać (instalację opisuje artykuł o pakietach):

library(stringr)

str_detect(files, "csv")            # like grepl(), data first
str_replace_all(s, "good", "great") # like gsub(), arguments reordered
str_length("hello")                 # like nchar()

Funkcje tekstowe bazowego R i tak warto znać: spotkasz je w każdym skrypcie, każdej odpowiedzi na Stack Overflow i każdym komunikacie o błędzie. Najpierw naucz się nazw z bazowego R; po stringr sięgnij, gdy niespójna kolejność argumentów zacznie cię irytować.

Najważniejsze informacje

  • Napisy zapisuje się zwyczajowo w cudzysłowach podwójnych; nchar() liczy znaki, length() liczy elementy wektora.
  • Łącz przez paste() / paste0(); sep skleja argumenty, collapse skleja wektor w jeden napis.
  • sprintf() obsługuje sformatowany wynik: %s, %d, %.2f.
  • sub() zamienia pierwsze dopasowanie, gsub() wszystkie, grepl() sprawdza dopasowania. Wszystkie domyślnie używają regex, więc przekaż fixed = TRUE dla dosłownego tekstu.
  • strsplit() zwraca listę (weź [[1]]); trimws() czyści wejście z nadmiarowymi spacjami.

Dalej: wprowadzanie tekstu do programów i wyprowadzanie go z nich, czyli wypisywanie przez print() i cat() oraz wczytywanie danych od użytkownika.

Najczęściej zadawane pytania

Jak łączyć napisy w R?

Przez paste() albo paste0(): R nie ma + dla napisów. paste("data", "science") daje "data science" (domyślnie ze spacją), a paste0("data", "science") łączy bez niczego. Użyj sep =, żeby zmienić separator, i collapse =, żeby złączyć cały wektor w jeden napis.

Jak sprawdzić długość napisu w R?

nchar("hello") zwraca 5, czyli liczbę znaków. length("hello") zwraca 1: w R length() liczy elementy wektora, a pojedynczy napis to wektor z jednym elementem. Mylenie length() z nchar() to klasyczny błąd początkujących.

Czym różni się sub() od gsub() w R?

Obie wyszukują i zamieniają, ale sub() zamienia tylko pierwsze dopasowanie, a gsub() ("global sub") zamienia wszystkie. Obie domyślnie traktują wzorzec jako wyrażenie regularne. Przekaż fixed = TRUE, żeby dopasować dosłowny tekst.

Jak podzielić napis w R?

strsplit(x, split) dzieli według wzorca, ale zwraca listę (bo potrafi podzielić wiele napisów naraz). Przy pojedynczym napisie weź pierwszy element: strsplit("a,b,c", ",")[[1]] daje wektor tekstowy "a" "b" "c".

Ilustracja języków programowania w Coddy

Ucz się programowania z Coddy

ZACZNIJ