2017-05-18 10 views
1

의 특정 용어에 단어의 근접을 계산하는 방법. 나는 비슷한 질문이 있다는 것을 알고 있지만, 필요한 답을 나에게 줄뿐만 아니라 도움이되는 곳을 알려주는 것도 없다. 그래서 나는 다음과 같은 텍스트가 있다고 가정하자 : 나는 15 내에 표시 어떤 단어를 볼 수 있도록하려면나는 문서의 특정 용어뿐만 아니라 (말씀으로) 평균 근접에 단어의 근접도를 계산하는 방법을 알아 내려고 노력하고 문서

song <- "Far over the misty mountains cold To dungeons deep and caverns old We 
must away ere break of day To seek the pale enchanted gold. The dwarves of 
yore made mighty spells, While hammers fell like ringing bells In places deep, 
where dark things sleep, In hollow halls beneath the fells. For ancient king 
and elvish lord There many a gleaming golden hoard They shaped and wrought, 
and light they caught To hide in gems on hilt of sword. On silver necklaces 
they strung The flowering stars, on crowns they hung The dragon-fire, in 
twisted wire They meshed the light of moon and sun. Far over the misty 
mountains cold To dungeons deep and caverns old We must away, ere break of 
day, To claim our long-forgotten gold. Goblets they carved there for 
themselves And harps of gold; where no man delves There lay they long, and 
many a song Was sung unheard by men or elves. The pines were roaring on the 
height, The winds were moaning in the night. The fire was red, it flaming 
spread; The trees like torches blazed with light. The bells were ringing in 
the dale And men they looked up with faces pale; The dragon’s ire more fierce 
than fire Laid low their towers and houses frail. The mountain smoked beneath 
the moon; The dwarves they heard the tramp of doom. They fled their hall to 
dying fall Beneath his feet, beneath the moon. Far over the misty mountains 
grim To dungeons deep and caverns dim We must away, ere break of day, 
To win our harps and gold from him!" 

를 왼쪽과 15 단어 양쪽에 (15 (I이 번호 교환 될 싶습니다) 오른쪽). "불"(또한 교환 할 수있는)이라는 단어가 나타날 때마다. 각 단어와 그 단어가이 "단어"에 나타나는 횟수를 "화재"의 각 사례마다보고 싶습니다. 예를 들어, "불"은 3 번 사용됩니다. 그 3 번 중 "빛"이라는 단어는 한쪽에서 두 번 15 단어 이내에 두 번 나옵니다. 단어를 표시하는 테이블, 지정된 근접도 내에서 나타나는 횟수 15, 최대 거리 (이 경우 12), 최소 거리 (7) 및 평균 거리 9.5).

나는이 작업을하기 위해 여러 단계와 패키지가 필요할 것이라고 생각했다. 나의 첫 번째 생각은 특정 용어에 대해 "창"을 선택할 수 있기 때문에 quanta에서 "kwic"함수를 사용하는 것이 었습니다. 그런 다음 kwic 결과에 기반한 용어의 빈도수는 그리 어렵지 않습니다 (빈도에 대한 중지 단어는 제거되었지만 단어 근접성 측정에는 해당되지 않음). 내 진짜 문제는 초점 기간에서 최대, 최소 및 평균 거리를 찾은 다음 주파수와 열 수에 따라 내림차순으로 열로 용어를 사용하여 멋진 표로 결과를 얻는 것입니다. 거리 및 평균 거리.

library(quanteda) 
library(tm) 

mysong <- char_tolower(song) 

toks <- tokens(mysong, remove_hyphens = TRUE, remove_punct = TRUE, 
remove_numbers = TRUE, remove_symbols = TRUE) 

mykwic <- kwic(toks, "fire", window = 15, valuetype ="fixed") 
thekwic <- as.character(mykwic) 

thekwic <- removePunctuation(thekwic) 
thekwic <- removeNumbers(thekwic) 
thekwic <- removeWords(thekwic, stopwords("en")) 

kwicFreq <- termFreq(thekwic) 

어떤 도움이 많이 감사합니다 : 여기

는 내가 지금까지 가지고있는 것입니다.

+0

문서의 크기는 얼마이며 분석은 항상 한 번에 한 학기가 될까요? 수백만 단어로 확장되지 않을 수있는 솔루션을 생각할 수 있습니다. –

+0

@David Robinson - 바로 지금 나는 햄릿 예를보고 있습니다. 정말 한 번에 하나의 문서 만 작업해야한다고 생각합니다. 나는 그것을 전체 셰익스피어 코퍼스 또는 비슷한 것으로 확장 할 수도 있습니다. 이것은 내가 여전히 10 만 단어 미만이라고 믿습니다. 셰익스피어에서 윌리엄 오브 티어 (William of Tire)에 이르기까지 다양한 텍스트에이 기능을 사용할 수 있기를 원하지만 수백만 단어의 단어에 속하는 것은 없습니다 ... 아직. – DHranger

+0

그런 경우 아래의 내 솔루션을 살펴보고 충분히 효율적인지 확인하십시오. 특히 'difference_inner_join'은 필요할 경우보다 효율적으로 만들 수 있습니다. –

답변

2

tidytextfuzzyjoin 패키지의 조합으로이 문제를 해결하는 게 좋을 것.

당신은 한 행 당 워드 데이터 프레임로를 토큰 화 position 열을 추가하고, 중지 단어 제거하여 시작할 수 있습니다

:

library(tidytext) 
library(dplyr) 

all_words <- data_frame(text = song) %>% 
    unnest_tokens(word, text) %>% 
    mutate(position = row_number()) %>% 
    filter(!word %in% tm::stopwords("en")) 

그런 다음 바로 단어 fire을 찾아 difference_inner_join()을 사용할 수 있습니다 fuzzyjoin에서 해당 행의 15 단어 내의 모든 행을 찾습니다. 그런 다음 group_by()summarize()을 사용하여 각 단어에 대해 원하는 통계를 얻을 수 있습니다. 이 경우

library(fuzzyjoin) 

nearby_words <- all_words %>% 
    filter(word == "fire") %>% 
    select(focus_term = word, focus_position = position) %>% 
    difference_inner_join(all_words, by = c(focus_position = "position"), max_dist = 15) %>% 
    mutate(distance = abs(focus_position - position)) 

words_summarized <- nearby_words %>% 
    group_by(word) %>% 
    summarize(number = n(), 
      maximum_distance = max(distance), 
      minimum_distance = min(distance), 
      average_distance = mean(distance)) %>% 
    arrange(desc(number)) 

출력 :이 방법은 또한 당신이 한 번에 여러 초점 단어 분석을 수행 할 수 있음을

# A tibble: 49 × 5 
     word number maximum_distance minimum_distance average_distance 
     <chr> <int>   <dbl>   <dbl>   <dbl> 
1  fire  3    0    0    0.0 
2 light  2    12    7    9.5 
3  moon  2    13    9    11.0 
4 bells  1    14    14    14.0 
5 beneath  1    11    11    11.0 
6 blazed  1    10    10    10.0 
7 crowns  1    5    5    5.0 
8  dale  1    15    15    15.0 
9 dragon  1    1    1    1.0 
10 dragon’s  1    5    5    5.0 
# ... with 39 more rows 

참고. 모두 filter(word == "fire")filter(word %in% c("fire", "otherword"))으로 변경하고 group_by(word)group_by(focus_word, word)으로 변경하면됩니다.

2

tidytext 대답은 좋은 일이지만, 도구는이에 대해 적용 할 수 있습니다 quanteda에있다. 윈도우 내에서 카운트하는 주요 기능은 kwic()이 아니라 fcm() (기능 동시 발생 매트릭스)입니다.

require(quanteda) 

# tokenize so that intra-word hyphens and punctuation are removed 
toks <- tokens(song, remove_punct = TRUE, remove_hyphens = TRUE) 

# all co-occurrences 
head(fcm(toks, window = 15, context = "window", count = "frequency")[, "fire"]) 
## Feature co-occurrence matrix of: 155 by 1 feature. 
## (showing first 6 documents and first feature) 
##   features 
## features fire 
## Far   1 
## over   1 
## the   5 
## misty  1 
## mountains 0 
## cold   0 

head(fcm(toks, window = 15, context = "window", count = "frequency")["light", "fire"]) 
## Feature co-occurrence matrix of: 1 by 1 feature. 
## 1 x 1 sparse Matrix of class "fcm" 
##   features 
## features fire 
## light 2 

대상에서 단어의 평균 거리를 얻으려면 거리에 대한 가중치 기능의 약간의 해킹이 필요합니다. 아래에서 가중치를 적용하여 위치에 따라 계수를 계산합니다.이 값은 합계가 계산 된 후 창 내의 총 빈도로 나뉠 때 가중 평균을 제공합니다. 예를 들어 "빛"당신의 예를 들어 : 최소 및 최대 위치를 얻기

# average distance 
fcm(toks, window = 15, context = "window", count = "weighted", weights = 1:15)["light", "fire"]/
    fcm(toks, window = 15, context = "window", count = "frequency")["light", "fire"] 
## 1 x 1 Matrix of class "dgeMatrix" 
##   features 
## light 9.5 
## features fire 

는 조금 더 복잡하다, 나는이 위치로 무게의 조합을 사용하여 "해킹"할 수있는 방법을 알아낼 수있는 반면 각 위치에서 바이너리 마스크를 사용하여 거리로 변환합니다. 너무 우아하게 생각하지 않는 한 깔끔한 해결책을 추천합니다.)