18  Práce se stringy

Předmětem této kapitoly jsou stringy, tedy nestrukturovaný text. O analýze nestrukturovaného toho lze napsat mnoho, mnohem více, než kolik dokáže pojmout tato kniha. Představíme si proto pouze úplné základy a to s pomocí balíčku stringr, který je součástí Tidyverse.

18.1 Detekce stringů

Náš data frame countries obsahuje proměnnou hd_title_name. Jedná se o titula a jméno hlavy dané země (k roku 2018). Na rozdíl od ostatních kategoriálních proměnných jsou jak titul, tak jméno osoby v jednom sloupci. Práce s nimi tedy bude vyžadovat o něco jiný přístup, než na jaký jsme zvyklí.

Jedním z nejběžnějších úkonů je vyhledávání vzorců (patterns) v textu. Pro vybraní zemí, jejichž hlavou je král, je možné zkombinovat již známou funkci filter() s funkcí str_detect(). Tato funkce vrátí hodnotu TRUE pro všechny řádky, ve kterých se nachází zvolený vzorec znaků, v našem případě “King”:

countries %>% 
  filter(str_detect(hd_title_name, pattern = "King")) %>% 
  select(country, hd_title_name)
# A tibble: 5 × 2
  country     hd_title_name          
  <chr>       <chr>                  
1 Belgium     King - Philippe        
2 Spain       King - Felipe VI       
3 Netherlands King - Willem-Alexander
4 Sweden      King - Carl XVI Gustaf 
5 Norway      King - Harald V        

Pomocí stejné funkce je možné hledat i více vzorců na jednou. Pro vyhledání všech království našem datasetu vyhledáme všechny hlavy států s titulem “King” nebo “Queen”. Oba hledané vzorce oddělíme znakem |, značící logický operátor OR:

countries %>% 
  filter(str_detect(hd_title_name, pattern = "King|Queen")) %>% 
  select(country, hd_title_name)
# A tibble: 7 × 2
  country        hd_title_name          
  <chr>          <chr>                  
1 Belgium        King - Philippe        
2 Denmark        Queen - Margrethe II   
3 Spain          King - Felipe VI       
4 Netherlands    King - Willem-Alexander
5 Sweden         King - Carl XVI Gustaf 
6 United Kingdom Queen - Elizabeth II   
7 Norway         King - Harald V        

V některých případech nám bude stačit vědět, kolikrát se určitý vzorec vyskytuje v datech. K tomu využijeme funkci str_count(). Protože pracujeme s vektorem stringů, zkombinujeme ji s funkcí sum(), abychom získali celkový počet monarchů napří všemi zeměmi:

sum(str_count(countries$hd_title_name, pattern = "King|Queen"))
[1] 7

18.2 Separace stringů

Pro usnadnění budoucí práce by bylo lepší proměnnou hd_title_name rozdělit do dvou nových proměnných. První z nových proměnných bude titul hlavy státu (title), druhou poté samotné jméno státnika (name). Toho nejjednodušeji docíleme pomocí funkce separate() z balíčku tidyr. Prvním argumentem této funkce, je string, který chceme rozdělit. Druhým argumentem, into, je vektor obsahující jména nových proměnných. Třetím argumentem je separátor (sep), který rozděluje obsah první a druhé z nových proměnných:

countries %>% 
  select(hd_title_name) %>% 
  separate(hd_title_name,
           into = c("title", "name"),
           sep = "-") %>% 
  head(5)
Warning: Expected 2 pieces. Additional pieces discarded in 4 rows [5, 11, 19,
30].
# A tibble: 5 × 2
  title      name           
  <chr>      <chr>          
1 King       " Philippe"    
2 President  " Rumen Radev" 
3 President  " Miloš Zeman" 
4 Queen      " Margrethe II"
5 President  " Frank"       

Tento kód téměř funguje, jak má, s jedním drobným problémem. Jak nás upozorňuje varování Warning: Expected 2 pieces. Additional pieces discarded in 4 rows [5, 11, 19, 30]. v několika jménech se objevil náš separátor - více než jednou. Protože jsme ale specifikovali pouze dvě nové proměnné, title a name, zahodili jsme omylem část jmen na řádcích 5, 11, 19 a 30. Napravit to můžeme pomocí argumentu extra = "merge", pomocí kterého zachováme všechny jména celé:

countries %>% 
  select(hd_title_name) %>% 
  separate(hd_title_name,
           into = c("title", "name"),
           sep = "-",
           extra = "merge") %>%
  head(5)
# A tibble: 5 × 2
  title      name                      
  <chr>      <chr>                     
1 King       " Philippe"               
2 President  " Rumen Radev"            
3 President  " Miloš Zeman"            
4 Queen      " Margrethe II"           
5 President  " Frank-Walter Steinmeier"

18.3 Transformace stringů

V některých případech je nutné stringy transformovat, buď do podoby vhodné pro analýzy nebo naopak do podoby vhodné pro prezentaci výstupů. Balíček stringr pro transformaci stringů nabízí hned několik funkcí. Funkce str_to_lower() převede všechny písmena na malá, str_to_upper() naopak na velká. str_to_sentence() převede první písmeno na velké a zbytek na malá, a nakonec str_to_title() převede první písmeno každého slova na velké a zbytek na malá:

str_to_lower(countries$hd_title_name) %>% head(5)
[1] "king - philippe"                     "president - rumen radev"            
[3] "president - miloš zeman"             "queen - margrethe ii"               
[5] "president - frank-walter steinmeier"
str_to_upper(countries$hd_title_name) %>% head(5)
[1] "KING - PHILIPPE"                     "PRESIDENT - RUMEN RADEV"            
[3] "PRESIDENT - MILOŠ ZEMAN"             "QUEEN - MARGRETHE II"               
[5] "PRESIDENT - FRANK-WALTER STEINMEIER"
str_to_sentence(countries$hd_title_name) %>% head(5)
[1] "King - philippe"                     "President - rumen radev"            
[3] "President - miloš zeman"             "Queen - margrethe ii"               
[5] "President - frank-walter steinmeier"
str_to_title(countries$hd_title_name) %>% head(5)
[1] "King - Philippe"                     "President - Rumen Radev"            
[3] "President - Miloš Zeman"             "Queen - Margrethe Ii"               
[5] "President - Frank-Walter Steinmeier"