Подсчитать количество вхождений слов из списка во фрейме данных в R

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

Поэтому я импортирую свой фрейм данных и список слов следующим образом.

df <- read.csv("tweets.csv")
wordlist <- read.csv("wordlist.csv")

Моя идея состояла в том, чтобы использовать цикл «for», который проходит через все слова в списке слов, подсчитывает их вхождения в фрейме данных df, а затем добавляет число в существующий список слов.

for (id in wordlist) 
{
wordlist$frequency <- sum(stri_detect_fixed(df$text, wordlist$word))
}

Ясно, что это не работает. Вместо этого он добавляет частоты ВСЕХ слов в моем списке слов к каждому слову во фрейме данных списка слов, который выглядит примерно так:

id  word     freuquency
1   the      1290
2   answer   1290
3   is       1290
4   wrong    1290

Я знаю, что это должно что-то делать с текущей переменной в моем цикле for. Любая помощь приветствуется :)


person Fabian    schedule 13.02.2018    source источник
comment
Вам нужно подмножить wordlist, используя индекс id где-то в вашем цикле for.   -  person David Klotz    schedule 13.02.2018
comment
Как предложил @DavidKlotz, вам нужно подмножить список слов, например, используя индексы, например. for(i in 1:nrow(wordlist)){wordlist$frequency[i]=sum(stri_detect_fixed(df$text, wordlist$word[i]))}. Конечно, вам нужно установить частоту до нуля перед циклом: wordlist$frequency = 0   -  person digEmAll    schedule 13.02.2018
comment
Кажется, что на это, вероятно, уже ответили на SO или в пакете. Вы должны задокументировать неудачные поиски, то есть ,,, если вы проводили какой-либо поиск.   -  person IRTFM    schedule 13.02.2018
comment
Можете ли вы дать нам некоторые примеры данных для работы?   -  person Matt W.    schedule 13.02.2018
comment
Пример данных приведен ниже @MattW.   -  person InfiniteFlash    schedule 13.02.2018
comment
@digEmAll Спасибо! Работает просто отлично.   -  person Fabian    schedule 13.02.2018
comment
@InfiniteFlashChess Фабиан опубликовал вопрос, поэтому я больше жду, чтобы понять, из чего состоит tweets.csv. Знаем ли мы, что это не отдельный файл?   -  person Matt W.    schedule 13.02.2018
comment
@МэттВ. tweets.csv — это фрейм данных из 42 переменных, содержащих твиты, полученные из API поиска Twitter. Это отдельный файл.   -  person Fabian    schedule 13.02.2018
comment
@ Фабиан, ты можешь перенести это в R, использовать dput(head(df)) и вывести структуру, чтобы мы могли использовать реальные данные для решения этой проблемы?   -  person Matt W.    schedule 13.02.2018
comment
@МэттВ. Вы можете ознакомиться с реальными данными здесь: drive.google.com /file/d/1fwPJNyo8c0rc6SmGZXrJPRJIgwo3KS60/   -  person Fabian    schedule 13.02.2018
comment
Справедливая точка Мэтт. Виноват.   -  person InfiniteFlash    schedule 13.02.2018
comment
Не беспокойтесь, у вас есть хорошее решение. Просто хотел узнать, как выглядели его данные :)   -  person Matt W.    schedule 13.02.2018


Ответы (2)


Я бы очистил твиты df, чтобы преобразовать их в нижний регистр, удалить стоп-слова, знаки препинания и т. д. (сначала очистите твиты, иначе вы получите «собака» и «собака» как два разных слова.

    x <- c("Heute oft gelesen: Hörmann: «Lieber die Fair-Play-Medaille» als Platz eins t.co/w75t1O3zWQ t.co/fQJ2eUbGLf",
"Lokalsport: Wallbaum versteigert Olympia-Kalender t.co/uH5HnJTwUE",
"Die „politischen Spiele“ sind hiermit eröffnet: t.co/EWSnRmNHlw via @de_sputnik")
wordlist <- c("Olympia", "hiermit", "Die")

Затем я бы создал sapply версию tolower и разобрал по пробелам. Затем я бы сгладил его, используя unlist, чтобы это был один вектор вместо списка, а затем безымянный, чтобы его было немного легче читать.

wordvec <- unname(unlist(sapply(x, function(z) str_split(tolower(z), " "))))

 [1] "heute"                   "oft"                     "gelesen:"                "hörmann:"                "«lieber"                
 [6] "die"                     "fair-play-medaille»"     "als"                     "platz"                   "eins"                   
[11] "t.co/w75t1o3zwq" "t.co/fqj2eubglf" "lokalsport:"             "wallbaum"                "versteigert"            
[16] "olympia-kalender"        "t.co/uh5hnjtwue" "die"                     "\u0084politischen"       "spiele\u0093"           
[21] "sind"                    "hiermit"                 "eröffnet:"               "t.co/ewsnrmnhlw" "via"                    
[26] "@de_sputnik"  

Я думаю, что это все еще довольно грязно. Я бы поискал какие-нибудь решения для очистки текста, такие как удаление специальных символов или использование grepl или что-то в этом роде, чтобы удалить http.

Чтобы отфильтровать список, чтобы он содержал только ваши слова, попробуйте:

wordvec[wordvec %in% tolower(wordlist)]
[1] "die"     "die"     "hiermit"

И тогда вы можете использовать table

table(wordvec[wordvec %in% tolower(wordlist)])

die hiermit 
  2       1 

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

person Matt W.    schedule 13.02.2018
comment
Хотя это хорошее решение, если есть пробелы, что, если бы их не было? Как бы вы работали с набором данных data, который я предоставил в своем ответе? - person InfiniteFlash; 13.02.2018
comment
Спасибо за подсказку со строчными буквами. Я включу это в свою программу. - person Fabian; 13.02.2018
comment
Мой ответ такой же, как и Фабиан, который только что ответил на ваш вопрос. собака была бы частью догмы, чего мы не хотим. Я не уверен, как решить эту проблему без отдельного файла данных. В конце концов, я думаю, нам нужно увидеть пример этого tweets.csv, чтобы понять реальную проблему. - person Matt W.; 13.02.2018
comment
@Fabian, можете ли вы привести пример своего CSV? - person Matt W.; 13.02.2018
comment
в качестве примечания я удалил http://, потому что редактор не разрешил мне публиковать без него. Они были включены в примеры текстов, которые я вытащил из документа. - person Matt W.; 14.02.2018
comment
@МэттВ. Спасибо! Я протестирую свою версию цикла с текстом, который включает в себя предварительно подсчитанные слова, и в случае несоответствия я попробую ваш способ. - person Fabian; 14.02.2018
comment
цикл определенно будет намного медленнее, чем векторизованное решение, такое как sapply - person Matt W.; 14.02.2018
comment
@МэттВ. хорошо знать. Я заставил его работать. Может быть, это правильный путь для длинных списков и большого количества данных... Спасибо за вашу поддержку! - person Fabian; 14.02.2018
comment
@Fabian это хорошая привычка: пытаться использовать семейство apply для циклов. В конечном итоге вы замедлите свой код, и все станет неуклюжим. Просто совет! - person Matt W.; 14.02.2018

Вот как я бы сделал это, используя sapply. Функция проверяет, содержит ли data 3 последовательных сочетания букв, и подсчитывает количество.

library(tidyverse)
library(stringi)

1000 случайно созданных строк длиной 100 букв

data <- replicate(100, sample(letters, size = 1000, replace = TRUE))%>%
        data.frame()%>%
        unite("string" , colnames(.) , sep = "", remove = TRUE)%>%
        .$string

head(data)
[1] "uggwaevptdbhhnmvunkcgdssgmulvyxxhnavbxxotwvkvvlycjeftmjufymwzofrhepraqfjlfslynkvbyommaawrvaoscuytfws"
[2] "vftwusfmkzwougqqupeeelcyaefkcxmrqphajcnerfiitttizmpjucohkvsawwiqolkvuofnuarmkriojlnnuvkcreekirfdpsil"
[3] "kbtkrlogalroiulppghcosrpqnryldiuigtsfopsldmcrmnwcwxlhtukvzsujkhqnillzmgwytpneigogvnsxtjgzuuhbjpdvtab"
[4] "cuzqynmbidfwubiuozuhudfqpynnfmkplnyetxxfzvobafmkggiqncykhvmmdrexvxdvtkljppudeiykxsapvpxbbheikydcagey"
[5] "qktsojaevqdegrqunbganigcnvkuxbydepgevcwqqkyekezjddbzqvepodyugwloauxygzgxnwlrjzkyvuihqdfxptwrpsvsdpzf"
[6] "ssfsgxhkankqbrzborfnnvcvqjaykicocxuydzelnuyfljjrhytzgndrktzfglhsuimwjqvvvtvqjsdlnwcbhfdfbsbgdmvfyjef"  

Ссылка на проверку data

three_consec_letters = expand.grid(letters, letters, letters)%>%
                       unite("consec", colnames(.), sep = "", remove = TRUE)%>%
                       .$consec

head(three_consec_letters)
[1] "aaa" "baa" "caa" "daa" "eaa" "faa"

Проверить и суммировать, если three_consec_letters находится в длинных строках

counts = sapply(three_consec_letters, function(x) stri_detect_fixed(data, x)%>%sum())

Результаты

head(counts)
aaa baa caa daa eaa faa 
  5   6   6   4   0   3 

Надеюсь это поможет.

person InfiniteFlash    schedule 13.02.2018
comment
Это еще один вариант, я думаю. Спасибо. Проблема здесь в том, что ваш счет для is также увеличится, если произойдет глупость. Мой фрейм данных содержит письменный язык из твитов, где у вас обычно есть разделитель между отдельными словами. И вы не хотите удалять этот разделитель. - person Fabian; 13.02.2018
comment
Если я не ошибаюсь, то, что я сделал выше, должно работать и с пробелами. Этот глупый пример немного смущает, да. Я должен подумать об этом. Я думаю, вам нужно разделить каждую строку на вектор и список. - person InfiniteFlash; 14.02.2018
comment
Вектор или список* - person InfiniteFlash; 14.02.2018