파일에서 n개의 가장 빈번한 단어 찾기

파일에서 n개의 가장 빈번한 단어 찾기

예를 들어 텍스트 파일에서 가장 일반적인 단어 10개를 찾고 싶습니다. 첫째, 솔루션은 키 입력(즉, 내 시간)에 최적화되어야 합니다. 둘째, 공연을 위해서다. 상위 10위 안에 들기 위해 지금까지 얻은 것은 다음과 같습니다.

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

사전에 (단어, numberOfOccurences)를 저장하고 값을 정렬하는 Java, Python 등의 프로그램을 만들거나 MapReduce를 사용할 수 있지만 키 입력에 맞게 최적화할 수 있습니다.

오탐(false positive)이 있나요? 더 좋은 방법이 있나요?

답변1

이는 "가장 일반적인 N개 항목"을 찾는 가장 일반적인 방법입니다. 단, a 가 누락되어 sort있고 a gratuitious 가 있습니다 cat.

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

sort앞에 a를 넣지 않으면 uniq -ci 잘못된 싱글톤 단어가 많이 나올 수 있습니다. uniq전체적인 고유성이 아닌 고유한 라인 실행만 수행됩니다.

"단어 중지"라는 트릭을 사용하고 싶을 수도 있습니다. 영어 텍스트(죄송하지만 여기서는 북미 단일 언어)를 보면 "of", "and", "the"와 같은 단어가 거의 항상 상위 2~3위를 차지합니다. 당신은 아마도 그것들을 제거하고 싶을 것입니다. GNU Groff 배포판 eign에는 꽤 괜찮은 불용어 목록이 포함된 파일 이름이 있습니다. 내 Arch 배포판에는 가 있지만 이전 Unix에서도 본 /usr/share/groff/current/eign것 같습니다 ./usr/share/dict/eign/usr/dict/eign

다음과 같이 불용어를 사용할 수 있습니다.

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

내 생각에는 대부분의 인간 언어에는 의미 있는 단어 빈도 수에서 제거된 유사한 "불용어"가 필요하지만 다른 언어의 불용어 목록을 어디에서 얻을 것을 제안해야 할지 모르겠습니다.

-won 플래그는 전체 fgrep단어 일치를 활성화합니다. 이렇게 하면 "a" 또는 "i"와 같이 단지 짧은 단어만 포함하는 단어에 대한 잘못된 긍정을 방지할 수 있습니다. 단어를 비교할 때 플래그 -i가 켜져 있고 uniq대소 fgrep문자를 무시합니다.

답변2

이것은 utf-8에서 더 잘 작동합니다.

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

답변3

AWK를 사용해 보자!

이 함수는 제공된 파일에서 발생하는 각 단어의 빈도를 내림차순으로 나열합니다.

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
}

다음과 같이 파일에서 호출할 수 있습니다.

$ cat your_file.txt | wordfrequency

상위 10개 단어에 대해서는 다음과 같습니다.

$ cat your_file.txt | wordfrequency | head -10

원천:AWK-와드 루비

답변4

하스켈을 사용해보자!

이게 언어전쟁으로 변질되는거 아닌가요?

import Data.List
import Data.Ord

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

용법:

cat input | wordfreq

또는:

cat input | wordfreq | head -10

관련 정보