Returns the co-occurence matrix of terms in the given iterable as a dictionary: {term1: {term2: count, term3: count, ...}}. A string can be given as an iterable over the words with: isplit(string). A file can be given as an iterable over the words with: isplit(chain(*open("f
(iterable, window=(-1,-1), match=lambda x: False, filter=lambda x: True, normalize=lambda x: x)
| 459 | if a: yield "".join(a) |
| 460 | |
| 461 | def cooccurrence(iterable, window=(-1,-1), match=lambda x: False, filter=lambda x: True, normalize=lambda x: x): |
| 462 | """ Returns the co-occurence matrix of terms in the given iterable |
| 463 | as a dictionary: {term1: {term2: count, term3: count, ...}}. |
| 464 | A string can be given as an iterable over the words with: isplit(string). |
| 465 | A file can be given as an iterable over the words with: isplit(chain(*open("file.txt"))). |
| 466 | The given match() function determines search terms. |
| 467 | The given filter() function determines co-occurring terms to count. |
| 468 | The given normalize() function can be used to remove punctuation, lowercase words, etc. |
| 469 | The given window, a (before, after)-tuple, specifies the size of the co-occurence window. |
| 470 | """ |
| 471 | class Sentinel(object): |
| 472 | pass |
| 473 | # Window of terms before and after the search term. |
| 474 | # Deque is more efficient than list.pop(0). |
| 475 | q = deque() |
| 476 | # Window size of terms alongside the search term. |
| 477 | # Note that window=(0,0) will return a dictionary of search term frequency |
| 478 | # (since it counts co-occurence with itself). |
| 479 | n = -min(0, window[0]) + max(window[1], 0) |
| 480 | m = {} |
| 481 | # Search terms may fall outside the co-occurrence window, e.g., window=(-3,-2). |
| 482 | # We add sentinel markers at the start and end of the given iterable. |
| 483 | for x in chain([Sentinel()] * n, iterable, [Sentinel()] * n): |
| 484 | q.append(x) |
| 485 | if len(q) > n: |
| 486 | # Given window q size and offset, |
| 487 | # find the index of the candidate term: |
| 488 | if window[1] >= 0: |
| 489 | i = -1 - window[1] |
| 490 | if window[1] < 0: |
| 491 | i = len(q) - 1 |
| 492 | if i < 0: |
| 493 | i = len(q) + i |
| 494 | x1 = q[i] |
| 495 | if not isinstance(x1, Sentinel): |
| 496 | x1 = normalize(x1) |
| 497 | if match(x1): |
| 498 | # Iterate the window and filter co-occurent terms. |
| 499 | for x2 in list(q).__getslice__(i+window[0], i+window[1]+1): |
| 500 | if not isinstance(x2, Sentinel): |
| 501 | x2 = normalize(x2) |
| 502 | if filter(x2): |
| 503 | if x1 not in m: |
| 504 | m[x1] = {} |
| 505 | if x2 not in m[x1]: |
| 506 | m[x1][x2] = 0 |
| 507 | m[x1][x2] += 1 |
| 508 | # Slide window. |
| 509 | q.popleft() |
| 510 | return m |
| 511 | |
| 512 | co_occurrence = cooccurrence |
| 513 |
nothing calls this directly
no test coverage detected
searching dependent graphs…