Finde die n häufigsten Wörter in einer Datei

Finde die n häufigsten Wörter in einer Datei

Ich möchte beispielsweise die 10 häufigsten Wörter in einer Textdatei finden. Erstens sollte die Lösung für Tastenanschläge (mit anderen Worten: meine Zeit) optimiert sein. Zweitens für die Leistung. Hier ist, was ich bisher habe, um in die Top 10 zu kommen:

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

Ich könnte ein Java-, Python- usw.-Programm erstellen, in dem ich (Wort, Anzahl der Vorkommen) in einem Wörterbuch speichere und den Wert sortiere, oder ich könnte MapReduce verwenden, aber ich optimiere für Tastenanschläge.

Gibt es Fehlalarme? Gibt es einen besseren Weg?

Antwort1

Das ist so ziemlich die gängigste Methode, um die „N häufigsten Dinge“ zu finden, außer dass ein fehlt sortund Sie ein unnötiges haben cat:

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

sortWenn Sie vor dem kein einfügen, uniq -ci erhalten Sie wahrscheinlich viele falsche Singleton-Wörter. uniqführt nur eindeutige Zeilenfolgen aus, nicht die allgemeine Eindeutigkeit.

Sie können einen Trick anwenden, „Stoppwörter“. Wenn Sie sich einen englischen Text ansehen (Entschuldigung, wir sind einsprachig in Nordamerika), belegen Wörter wie „of“, „and“ und „the“ fast immer die ersten zwei oder drei Plätze. Sie möchten sie wahrscheinlich eliminieren. Die GNU Groff-Distribution enthält eine Datei mit dem Namen, eigndie eine ziemlich gute Liste von Stoppwörtern enthält. Meine Arch-Distribution hat /usr/share/groff/current/eign, aber ich glaube, ich habe in alten Unix-Versionen auch /usr/share/dict/eignoder gesehen./usr/dict/eign

Sie können Stoppwörter wie diese verwenden:

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

Ich vermute, dass in den meisten menschlichen Sprachen ähnliche „Stoppwörter“ aus aussagekräftigen Worthäufigkeitszählungen entfernt werden müssen, weiß aber nicht, wo ich Listen mit Stoppwörtern für andere Sprachen finden kann.

Das -wFlag fgrepaktiviert die Übereinstimmung ganzer Wörter. Dadurch werden falsche Ergebnisse bei Wörtern vermieden, die nur kurze Stoppwörter enthalten, wie „a“ oder „i“. Das -iFlag aktiviert uniqund fgrepignoriert die Groß-/Kleinschreibung beim Vergleichen von Wörtern.

Antwort2

Das funktioniert besser mit UTF-8:

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

Antwort3

Lasst uns AWK nutzen!

Diese Funktion listet die Häufigkeit jedes Worts in der bereitgestellten Datei in absteigender Reihenfolge auf:

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
}

Sie können es für Ihre Datei folgendermaßen aufrufen:

$ cat your_file.txt | wordfrequency

und für die Top 10 Wörter:

$ cat your_file.txt | wordfrequency | head -10

Quelle:AWK-Ward Ruby

Antwort4

Lasst uns Haskell verwenden!

Das entwickelt sich zu einem Sprachenkrieg, nicht wahr?

import Data.List
import Data.Ord

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

Verwendung:

cat input | wordfreq

Alternative:

cat input | wordfreq | head -10

verwandte Informationen