Странное поведение функции mutate из пакета dplyr в R

Я работаю над набором с размерами

dim(data)
[1] 419612      2

Где второй столбец выглядит примерно так:

> unique(data[1:50,"topics"])
[1] {"dom":2.0,"moda":3.0,"rodzina":1.55,"praca":1.42,"finanse":1.96,"edukacja":1.67,"sport":1.96,"muzyka":1.52,"kuchnia":1.8,"plotka":1.8,"zdrowie":1.12,"kibic":1.8,"uroda":2.32,"gra":2.94,"motoryzacja":1.33,"kultura":1.42,"film":3.14,"podróż":1.9,"technologia":1.31}
[2] {"rodzina":2.99,"kultura":4.46,"muzyka":4.5}                                                                                                                                                                                                                            
[3] {"dom":1.93,"rodzina":5.37,"zwierzęta":3.0,"praca":4.3,"finanse":2.11,"sport":2.1,"muzyka":2.99,"nieruchomość":2.8,"kuchnia":6.4,"plotka":2.1,"zdrowie":3.79,"gra":4.25,"motoryzacja":2.57,"kultura":3.13,"film":4.4,"podróż":3.21}                                     
[4] {"plotka":9.5,"uroda":10.06,"kultura":15.67,"muzyka":29.97}                                                                                                                                                                                                             
[5] {"dom":2.99,"rodzina":2.5,"edukacja":3.85,"sport":1.17,"muzyka":1.23,"nieruchomość":2.95,"kuchnia":1.42,"wnętrze":1.33,"kibic":1.17,"ogród":1.33,"motoryzacja":1.17,"film":1.17,"podróż":1.57}                                                                          
[6] {"kuchnia":4.38,"plotka":1.33,"rodzina":1.61,"film":1.33}                                                                                                                                                                                                               
37530 Levels: {"biznes":1.0} ... {"zwierzęta":9.96,"podróż":9.97}

Для каждой строки я хотел бы выбрать слово из столбца topics, которое имеет наивысшую оценку после знака :. Я пытался использовать функцию mutate из пакета dplyr, похоже, это не сработало. Операции над персонажами сделаны с помощью пакета stringi, который является более быстрой версией stringr. Мой код и результат этой операции ниже. Кто-нибудь знает, почему я получаю одно и то же значение в каждой строке после этой операции и как добиться желаемого результата без использования цикла for?

> data2 <- data %>%
+   mutate( xx = topics %>%
+             stri_extract_all_regex(pattern = "[a-zA-Z0-9óśćłźżęą\\.\\s]+") %>% 
+             unlist %>% 
+             data.frame( topic = .[seq(1,length(.), by=2)], 
+                         waga = .[seq(2,length(.), by=2)] )  %>% 
+             select( topic, waga) %>% arrange( desc( waga)) %>%
+             unique() %>%
+             .[1,1]
+             )
> table(data2$xx)[ which(table(data2$xx) > 1) ]
kuchnia 
 419612 

Я добавил дополнительный столбец nr, который является номером строки, а затем я тупо поставил group_byed в этом столбце и summarised вместо mutate и добился того, чего хотел... но я не горжусь своим кодом. Любые другие идеи?

daneBC1 <- data %>% 
  group_by( nr)  %>%
  summarise( bc1 = topics %>%
               stri_extract_all_regex(pattern = "[a-zA-Z0-9óśćłźżęą\\.\\s]+") %>% 
               unlist %>% 
               data.frame( topic = .[seq(1,length(.), by=2)], 
                           waga = .[seq(2,length(.), by=2)] )  %>% 
               select( topic, waga) %>% arrange( desc( waga)) %>%
               unique() %>%
               .[1,1] )



daneBC1$bc1 %>% table

        dom    edukacja        film     finanse         gra       kibic     kuchnia     kultura 
     119802       79487       55569       38134       30425       21757       16371       12356 
       moda motoryzacja      muzyka      plotka      podróż       praca     rodzina       sport 
      11103        7264        6357        4855        3520        3005        2317        2183 
technologia       uroda     zdrowie 
       1441        1055         740 

Пример данных

library(archivist)
data <- loadFromGithubRepo( "97f74c5a10f510cce39eafb0d9a1a9e8", 
user="MarcinKosinski", repo="Museum", value = TRUE )

person Marcin Kosiński    schedule 19.04.2015    source источник
comment
Почему вы хотите использовать регулярные выражения, а не читать это как JSON? Также вы проверили, не заключается ли проблема в том, что данные сохраняются как фактор, а не как символ (зачем фактор здесь?)?   -  person Tim    schedule 19.04.2015
comment
Кстати, вы можете предоставить образцы данных?   -  person Tim    schedule 19.04.2015
comment
@Tim Я обновил свой комментарий с примерами данных в конце.   -  person Marcin Kosiński    schedule 19.04.2015
comment
@Tim Теперь я вижу, что применение функции fromJSON из пакета rjson к каждой строке может быть более читаемым, но, как вы видите, простое регулярное выражение также работает :), но mutatefunction не ..   -  person Marcin Kosiński    schedule 19.04.2015
comment
Да, но я бы все же придерживался одной из библиотек JSON, потому что (а) они предназначены для таких структур данных и поэтому, вероятно, менее подвержены ошибкам, (б) вероятно, быстрее, чем использование регулярных выражений. Если производительность является проблемой в вашем проекте, я бы проверил это.   -  person Tim    schedule 19.04.2015
comment
Спасибо за предложение. Я буду помнить об этом в будущем.   -  person Marcin Kosiński    schedule 19.04.2015
comment
Ого @MrFlick! Теперь я вижу это. Любая идея о том, как выполнить эту операцию с помощью dply-fast-functions?   -  person Marcin Kosiński    schedule 19.04.2015


Ответы (1)


Ваша функция mutate() не "векторизована". Mutate не работает со строками за раз, он работает со всеми столбцами как с векторами. Ваше извлечение unlist и .[1,1] принимает значения для всех строк и сводится к одному вектору и одному значению.

Вы можете сделать функцию векторизованного преобразования с помощью

extr <- Vectorize(. %>%
         stri_extract_all_regex(pattern = "[a-zA-Z0-9óśćłźżęą\\.\\s]+") %>% 
         unlist %>% 
         data.frame( topic = .[seq(1,length(.), by=2)], 
                     waga = .[seq(2,length(.), by=2)] )  %>% 
         select( topic, waga) %>% arrange( desc( waga)) %>%
         unique() %>%
         .[1,1])

а затем использовать его с

data %>% mutate( xx = extr(topics))

хотя я согласен с другими, что, поскольку у вас есть данные JSON, было бы лучше правильно проанализировать эти данные с помощью парсера JSON, а не пытаться заново изобретать колесо с помощью регулярных выражений.

person MrFlick    schedule 19.04.2015