encontre n palavras mais frequentes em um arquivo

encontre n palavras mais frequentes em um arquivo

Quero encontrar, digamos, as 10 palavras mais comuns em um arquivo de texto. Em primeiro lugar, a solução deve ser otimizada para pressionamentos de tecla (em outras palavras - meu tempo). Em segundo lugar, pelo desempenho. Aqui está o que tenho até agora para ficar entre os 10 primeiros:

cat test.txt | tr -c '[:alnum:]' '[\n*]' | uniq -c | sort -nr | head  -10
  6 k
  2 g
  2 e
  2 a
  1 r
  1 k22
  1 k
  1 f
  1 eeeeeeeeeeeeeeeeeeeee
  1 d

Eu poderia fazer um programa java, python etc. onde armazeno (palavra, númeroOfOccurences) em um dicionário e classifico o valor ou poderia usar MapReduce, mas otimizo para pressionamentos de tecla.

Existem falsos positivos? Existe uma maneira melhor?

Responder1

Essa é praticamente a maneira mais comum de encontrar "N coisas mais comuns", exceto que você está faltando um sorte tem um gratuito cat:

tr -c '[:alnum:]' '[\n*]' < test.txt | sort | uniq -ci | sort -nr | head  -10

Se você não colocar um sortantes de, uniq -ci provavelmente obterá muitas palavras falsas de singleton. uniqapenas execuções únicas de linhas, não exclusividade geral.

Você pode querer usar um truque, "palavras de parada". Se você estiver olhando para um texto em inglês (desculpe, monolíngue norte-americano aqui), palavras como "de", "e", "o" quase sempre ocupam os dois ou três primeiros lugares. Você provavelmente deseja eliminá-los. A distribuição GNU Groff possui um arquivo nomeado eignque contém uma lista bastante decente de palavras irrelevantes. Minha distro Arch tem /usr/share/groff/current/eign, mas acho que também vi /usr/share/dict/eignou /usr/dict/eignem Unixes antigos.

Você pode usar palavras irrelevantes como esta:

tr -c '[:alnum:]' '[\n*]' < test.txt |
fgrep -v -w -f -i /usr/share/groff/current/eign |
sort | uniq -ci | sort -nr | head  -10

Meu palpite é que a maioria dos idiomas humanos precisa de "palavras de parada" semelhantes removidas das contagens de frequência de palavras significativas, mas não sei onde sugerir a obtenção de listas de palavras de parada de outros idiomas.

O -wsinalizador ativado fgreppermite a correspondência de palavras inteiras. Isso evita falsos positivos em palavras que contêm apenas palavras curtas, como "a" ou "i". O -isinalizador ativa uniqe fgrepignora maiúsculas e minúsculas ao comparar palavras.

Responder2

Isso funciona melhor com utf-8:

$ sed -e 's/\s/\n/g' < test.txt | sort | uniq -c | sort -nr | head  -10

Responder3

Vamos usar o AWK!

Esta função lista a frequência de cada palavra que ocorre no arquivo fornecido em ordem decrescente:

function wordfrequency() {
  awk '
     BEGIN { FS="[^a-zA-Z]+" } {
         for (i=1; i<=NF; i++) {
             word = tolower($i)
             words[word]++
         }
     }
     END {
         for (w in words)
              printf("%3d %s\n", words[w], w)
     } ' | sort -rn
}

Você pode chamá-lo em seu arquivo assim:

$ cat your_file.txt | wordfrequency

e para as 10 principais palavras:

$ cat your_file.txt | wordfrequency | head -10

Fonte:Ruby AWK

Responder4

Vamos usar Haskell!

Isto está se transformando em uma guerra linguística, não é?

import Data.List
import Data.Ord

main = interact $ (=<<) (\x -> show (length x) ++ " - " ++ head x ++ "\n")
                . sortBy (flip $ comparing length)
                . group . sort
                . words

Uso:

cat input | wordfreq

Alternativamente:

cat input | wordfreq | head -10

informação relacionada