2016-04-15 4 views
0

Я использую dplyr для разбора столбца, содержащего предложения, и вычисления количества nграмм для каждого из них. Вот пример, демонстрирующий проблему, с которой я столкнулся.Использование mutate для получения числа ngrams

Как вы видите, ожидается, что ngram_cnt будет 3 и 4, но результат будет равен столбцу 3,3. Проблема в том, что код возвращает число ngrams для первого предложения, игнорируя остальные. Вы можете попытаться добавить дополнительные предложения, имеющие тот же эффект. Что я делаю не так?

library(NLP) 
library(dplyr) 
library(stringr) 

phrases <- c("this is the first", "and then comes the second") 
df <- data.frame(phrase = phrases, id = c(1, 2)) 
df %>% mutate(ngram_cnt = length(ngrams(str_split(phrase, "\\s")[[1]], 2))) 

Если я скажу,

phrases <- c("this is the first", "and then comes the second", 
      "and the third which is even longer") 
df <- data.frame(phrase = phrases, id = c(1, 2, 3)) 
df %>% mutate(ngram_cnt = str_length(phrase)) 

тогда я получаю ожидаемые результаты (а именно, длина каждого предложения).

ответ

2

Это потому, что в

df %>% mutate(ngram_cnt = length(ngrams(str_split(phrase, "\\s")[[1]], 2))) 

[[1]] выбрать только разделение на первом предложении это то же самое, как:

length(ngrams(str_split(phrases, "\\s")[[1]], 2)) 
# [1] 3 

И после того, как mutate ставит 3 в каждой строке

phrases <- c("this is the first", "and then comes the second") 
df <- data.frame(phrase = phrases, id = c(1, 2)) 
library("dplyr") 

Вы можете применить расчет по ряду с rowwise:

df %>% rowwise() %>% mutate(ngram_cnt = length(ngrams(str_split(phrase, "\\s")[[1]], n = 2))) 
# Source: local data frame [2 x 3] 
# Groups: <by row> 
# 
#      phrase id ngram_cnt 
#      (fctr) (dbl)  (int) 
# 1   this is the first  1   3 
# 2 and then comes the second  2   4 

Или с group_by если у вас идентификатор является уникальным:

df %>% group_by(id) %>% mutate(ngram_cnt = length(ngrams(str_split(phrase, "\\s")[[1]], n = 2))) 
# Source: local data frame [2 x 3] 
# Groups: id [2] 
# 
#      phrase id ngram_cnt 
#      (fctr) (dbl)  (int) 
# 1   this is the first  1   3 
# 2 and then comes the second  2   4 

Или вы можете векторизации функции, вычислить длину ngrams:

length_ngrams <- function(x) { 
    length(ngrams(str_split(x, "\\s")[[1]], n = 2)) 
} 
length_ngrams <- Vectorize(length_ngrams) 
df %>% mutate(ngram_cnt = length_ngrams(phrase)) 
#      phrase id ngram_cnt 
# 1   this is the first 1   3 
# 2 and then comes the second 2   4