nltk 3.2__zip → 3.3__zip

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (406) hide show
  1. {nltk-3.2 → nltk-3.3}/INSTALL.txt +6 -6
  2. {nltk-3.2 → nltk-3.3}/LICENSE.txt +13 -13
  3. {nltk-3.2 → nltk-3.3}/MANIFEST.in +6 -6
  4. {nltk-3.2/nltk.egg-info → nltk-3.3}/PKG-INFO +13 -5
  5. nltk-3.2/README.txt → nltk-3.3/README.md +49 -48
  6. nltk-3.3/nltk/VERSION +1 -0
  7. {nltk-3.2 → nltk-3.3}/nltk/__init__.py +185 -185
  8. {nltk-3.2 → nltk-3.3}/nltk/app/__init__.py +52 -53
  9. {nltk-3.2 → nltk-3.3}/nltk/app/chartparser_app.py +2276 -2276
  10. {nltk-3.2 → nltk-3.3}/nltk/app/chunkparser_app.py +1262 -1264
  11. {nltk-3.2 → nltk-3.3}/nltk/app/collocations_app.py +347 -350
  12. {nltk-3.2 → nltk-3.3}/nltk/app/concordance_app.py +568 -570
  13. {nltk-3.2 → nltk-3.3}/nltk/app/nemo_app.py +156 -155
  14. {nltk-3.2 → nltk-3.3}/nltk/app/rdparser_app.py +892 -894
  15. {nltk-3.2 → nltk-3.3}/nltk/app/srparser_app.py +809 -809
  16. {nltk-3.2 → nltk-3.3}/nltk/app/wordfreq_app.py +32 -32
  17. {nltk-3.2 → nltk-3.3}/nltk/app/wordnet_app.py +968 -968
  18. {nltk-3.2 → nltk-3.3}/nltk/book.py +91 -90
  19. {nltk-3.2 → nltk-3.3}/nltk/ccg/__init__.py +22 -22
  20. {nltk-3.2 → nltk-3.3}/nltk/ccg/api.py +359 -335
  21. {nltk-3.2 → nltk-3.3}/nltk/ccg/chart.py +394 -361
  22. {nltk-3.2 → nltk-3.3}/nltk/ccg/combinator.py +343 -312
  23. {nltk-3.2 → nltk-3.3}/nltk/ccg/lexicon.py +328 -290
  24. nltk-3.3/nltk/ccg/logic.py +46 -0
  25. {nltk-3.2 → nltk-3.3}/nltk/chat/__init__.py +49 -49
  26. {nltk-3.2 → nltk-3.3}/nltk/chat/eliza.py +244 -244
  27. {nltk-3.2 → nltk-3.3}/nltk/chat/iesha.py +140 -140
  28. {nltk-3.2 → nltk-3.3}/nltk/chat/rude.py +92 -92
  29. {nltk-3.2 → nltk-3.3}/nltk/chat/suntsu.py +117 -117
  30. {nltk-3.2 → nltk-3.3}/nltk/chat/util.py +122 -120
  31. {nltk-3.2 → nltk-3.3}/nltk/chat/zen.py +282 -282
  32. {nltk-3.2 → nltk-3.3}/nltk/chunk/__init__.py +190 -190
  33. {nltk-3.2 → nltk-3.3}/nltk/chunk/api.py +51 -51
  34. {nltk-3.2 → nltk-3.3}/nltk/chunk/named_entity.py +331 -331
  35. {nltk-3.2 → nltk-3.3}/nltk/chunk/regexp.py +1390 -1384
  36. {nltk-3.2 → nltk-3.3}/nltk/chunk/util.py +600 -600
  37. {nltk-3.2 → nltk-3.3}/nltk/classify/__init__.py +98 -98
  38. {nltk-3.2 → nltk-3.3}/nltk/classify/api.py +193 -193
  39. {nltk-3.2 → nltk-3.3}/nltk/classify/decisiontree.py +295 -295
  40. {nltk-3.2 → nltk-3.3}/nltk/classify/maxent.py +1510 -1492
  41. {nltk-3.2 → nltk-3.3}/nltk/classify/megam.py +179 -178
  42. {nltk-3.2 → nltk-3.3}/nltk/classify/naivebayes.py +245 -242
  43. {nltk-3.2 → nltk-3.3}/nltk/classify/positivenaivebayes.py +170 -170
  44. {nltk-3.2 → nltk-3.3}/nltk/classify/rte_classify.py +160 -191
  45. {nltk-3.2 → nltk-3.3}/nltk/classify/scikitlearn.py +153 -151
  46. {nltk-3.2 → nltk-3.3}/nltk/classify/senna.py +183 -181
  47. {nltk-3.2 → nltk-3.3}/nltk/classify/svm.py +15 -15
  48. {nltk-3.2 → nltk-3.3}/nltk/classify/tadm.py +113 -112
  49. {nltk-3.2 → nltk-3.3}/nltk/classify/textcat.py +193 -193
  50. {nltk-3.2 → nltk-3.3}/nltk/classify/util.py +324 -312
  51. {nltk-3.2 → nltk-3.3}/nltk/classify/weka.py +346 -345
  52. {nltk-3.2 → nltk-3.3}/nltk/cluster/__init__.py +86 -86
  53. {nltk-3.2 → nltk-3.3}/nltk/cluster/api.py +74 -70
  54. {nltk-3.2 → nltk-3.3}/nltk/cluster/em.py +247 -247
  55. {nltk-3.2 → nltk-3.3}/nltk/cluster/gaac.py +168 -168
  56. {nltk-3.2 → nltk-3.3}/nltk/cluster/kmeans.py +221 -221
  57. {nltk-3.2 → nltk-3.3}/nltk/cluster/util.py +304 -289
  58. nltk-3.3/nltk/collections.py +640 -0
  59. {nltk-3.2 → nltk-3.3}/nltk/collocations.py +388 -388
  60. nltk-3.3/nltk/compat.py +365 -0
  61. {nltk-3.2 → nltk-3.3}/nltk/corpus/__init__.py +341 -320
  62. {nltk-3.2 → nltk-3.3}/nltk/corpus/europarl_raw.py +44 -44
  63. {nltk-3.2 → nltk-3.3}/nltk/corpus/reader/__init__.py +147 -145
  64. {nltk-3.2 → nltk-3.3}/nltk/corpus/reader/aligned.py +115 -114
  65. {nltk-3.2 → nltk-3.3}/nltk/corpus/reader/api.py +448 -446
  66. {nltk-3.2 → nltk-3.3}/nltk/corpus/reader/bnc.py +252 -252
  67. {nltk-3.2 → nltk-3.3}/nltk/corpus/reader/bracket_parse.py +227 -227
  68. {nltk-3.2 → nltk-3.3}/nltk/corpus/reader/categorized_sents.py +179 -178
  69. {nltk-3.2 → nltk-3.3}/nltk/corpus/reader/chasen.py +140 -139
  70. {nltk-3.2 → nltk-3.3}/nltk/corpus/reader/childes.py +522 -494
  71. {nltk-3.2 → nltk-3.3}/nltk/corpus/reader/chunked.py +212 -212
  72. {nltk-3.2 → nltk-3.3}/nltk/corpus/reader/cmudict.py +97 -95
  73. {nltk-3.2 → nltk-3.3}/nltk/corpus/reader/comparative_sents.py +280 -278
  74. {nltk-3.2 → nltk-3.3}/nltk/corpus/reader/conll.py +528 -521
  75. {nltk-3.2 → nltk-3.3}/nltk/corpus/reader/crubadan.py +116 -116
  76. {nltk-3.2 → nltk-3.3}/nltk/corpus/reader/dependency.py +101 -101
  77. {nltk-3.2 → nltk-3.3}/nltk/corpus/reader/framenet.py +3059 -2093
  78. {nltk-3.2 → nltk-3.3}/nltk/corpus/reader/ieer.py +112 -111
  79. {nltk-3.2 → nltk-3.3}/nltk/corpus/reader/indian.py +85 -86
  80. {nltk-3.2 → nltk-3.3}/nltk/corpus/reader/ipipan.py +332 -331
  81. {nltk-3.2 → nltk-3.3}/nltk/corpus/reader/knbc.py +187 -187
  82. {nltk-3.2 → nltk-3.3}/nltk/corpus/reader/lin.py +156 -156
  83. {nltk-3.2 → nltk-3.3}/nltk/corpus/reader/mte.py +311 -310
  84. {nltk-3.2 → nltk-3.3}/nltk/corpus/reader/nkjp.py +429 -428
  85. {nltk-3.2 → nltk-3.3}/nltk/corpus/reader/nombank.py +421 -421
  86. {nltk-3.2 → nltk-3.3}/nltk/corpus/reader/nps_chat.py +73 -73
  87. {nltk-3.2 → nltk-3.3}/nltk/corpus/reader/opinion_lexicon.py +115 -115
  88. {nltk-3.2 → nltk-3.3}/nltk/corpus/reader/panlex_lite.py +165 -165
  89. nltk-3.3/nltk/corpus/reader/pl196x.py +292 -0
  90. {nltk-3.2 → nltk-3.3}/nltk/corpus/reader/plaintext.py +232 -233
  91. {nltk-3.2 → nltk-3.3}/nltk/corpus/reader/ppattach.py +96 -95
  92. {nltk-3.2 → nltk-3.3}/nltk/corpus/reader/propbank.py +479 -481
  93. {nltk-3.2 → nltk-3.3}/nltk/corpus/reader/pros_cons.py +128 -126
  94. {nltk-3.2 → nltk-3.3}/nltk/corpus/reader/reviews.py +330 -328
  95. {nltk-3.2 → nltk-3.3}/nltk/corpus/reader/rte.py +144 -146
  96. {nltk-3.2 → nltk-3.3}/nltk/corpus/reader/semcor.py +256 -256
  97. {nltk-3.2 → nltk-3.3}/nltk/corpus/reader/senseval.py +203 -201
  98. {nltk-3.2 → nltk-3.3}/nltk/corpus/reader/sentiwordnet.py +137 -137
  99. {nltk-3.2 → nltk-3.3}/nltk/corpus/reader/sinica_treebank.py +75 -75
  100. {nltk-3.2 → nltk-3.3}/nltk/corpus/reader/string_category.py +60 -59
  101. {nltk-3.2 → nltk-3.3}/nltk/corpus/reader/switchboard.py +119 -119
  102. {nltk-3.2 → nltk-3.3}/nltk/corpus/reader/tagged.py +295 -294
  103. {nltk-3.2 → nltk-3.3}/nltk/corpus/reader/timit.py +452 -450
  104. {nltk-3.2 → nltk-3.3}/nltk/corpus/reader/toolbox.py +68 -68
  105. {nltk-3.2 → nltk-3.3}/nltk/corpus/reader/twitter.py +155 -157
  106. {nltk-3.2 → nltk-3.3}/nltk/corpus/reader/udhr.py +80 -80
  107. {nltk-3.2 → nltk-3.3}/nltk/corpus/reader/util.py +804 -800
  108. nltk-3.3/nltk/corpus/reader/verbnet.py +595 -0
  109. nltk-3.3/nltk/corpus/reader/wordlist.py +134 -0
  110. {nltk-3.2 → nltk-3.3}/nltk/corpus/reader/wordnet.py +2108 -2036
  111. {nltk-3.2 → nltk-3.3}/nltk/corpus/reader/xmldocs.py +392 -387
  112. {nltk-3.2 → nltk-3.3}/nltk/corpus/reader/ycoe.py +243 -242
  113. {nltk-3.2 → nltk-3.3}/nltk/corpus/util.py +144 -127
  114. {nltk-3.2 → nltk-3.3}/nltk/data.py +1487 -1451
  115. {nltk-3.2 → nltk-3.3}/nltk/decorators.py +219 -215
  116. {nltk-3.2 → nltk-3.3}/nltk/downloader.py +2278 -2274
  117. {nltk-3.2 → nltk-3.3}/nltk/draw/__init__.py +27 -27
  118. {nltk-3.2 → nltk-3.3}/nltk/draw/cfg.py +774 -777
  119. {nltk-3.2 → nltk-3.3}/nltk/draw/dispersion.py +58 -58
  120. {nltk-3.2 → nltk-3.3}/nltk/draw/table.py +1098 -1098
  121. {nltk-3.2 → nltk-3.3}/nltk/draw/tree.py +963 -966
  122. {nltk-3.2 → nltk-3.3}/nltk/draw/util.py +2356 -2356
  123. {nltk-3.2 → nltk-3.3}/nltk/featstruct.py +2617 -2500
  124. {nltk-3.2 → nltk-3.3}/nltk/grammar.py +1559 -1516
  125. {nltk-3.2 → nltk-3.3}/nltk/help.py +56 -56
  126. {nltk-3.2 → nltk-3.3}/nltk/inference/__init__.py +20 -20
  127. {nltk-3.2 → nltk-3.3}/nltk/inference/api.py +597 -589
  128. {nltk-3.2 → nltk-3.3}/nltk/inference/discourse.py +612 -608
  129. {nltk-3.2 → nltk-3.3}/nltk/inference/mace.py +311 -311
  130. {nltk-3.2 → nltk-3.3}/nltk/inference/nonmonotonic.py +509 -509
  131. {nltk-3.2 → nltk-3.3}/nltk/inference/prover9.py +431 -431
  132. {nltk-3.2 → nltk-3.3}/nltk/inference/resolution.py +687 -687
  133. {nltk-3.2 → nltk-3.3}/nltk/inference/tableau.py +607 -607
  134. {nltk-3.2 → nltk-3.3}/nltk/internals.py +982 -982
  135. {nltk-3.2 → nltk-3.3}/nltk/jsontags.py +63 -63
  136. {nltk-3.2 → nltk-3.3}/nltk/lazyimport.py +142 -142
  137. {nltk-3.2 → nltk-3.3}/nltk/metrics/__init__.py +30 -29
  138. {nltk-3.2 → nltk-3.3}/nltk/metrics/agreement.py +421 -401
  139. nltk-3.3/nltk/metrics/aline.py +607 -0
  140. {nltk-3.2 → nltk-3.3}/nltk/metrics/association.py +414 -410
  141. {nltk-3.2 → nltk-3.3}/nltk/metrics/confusionmatrix.py +206 -206
  142. {nltk-3.2 → nltk-3.3}/nltk/metrics/distance.py +207 -202
  143. {nltk-3.2 → nltk-3.3}/nltk/metrics/paice.py +381 -381
  144. {nltk-3.2 → nltk-3.3}/nltk/metrics/scores.py +228 -228
  145. {nltk-3.2 → nltk-3.3}/nltk/metrics/segmentation.py +231 -232
  146. {nltk-3.2 → nltk-3.3}/nltk/metrics/spearman.py +69 -69
  147. {nltk-3.2 → nltk-3.3}/nltk/misc/__init__.py +11 -11
  148. {nltk-3.2 → nltk-3.3}/nltk/misc/babelfish.py +10 -10
  149. {nltk-3.2 → nltk-3.3}/nltk/misc/chomsky.py +135 -133
  150. {nltk-3.2 → nltk-3.3}/nltk/misc/minimalset.py +83 -83
  151. {nltk-3.2 → nltk-3.3}/nltk/misc/sort.py +157 -157
  152. {nltk-3.2 → nltk-3.3}/nltk/misc/wordfinder.py +129 -129
  153. {nltk-3.2 → nltk-3.3}/nltk/parse/__init__.py +81 -80
  154. {nltk-3.2 → nltk-3.3}/nltk/parse/api.py +66 -66
  155. {nltk-3.2 → nltk-3.3}/nltk/parse/bllip.py +282 -282
  156. {nltk-3.2 → nltk-3.3}/nltk/parse/chart.py +1682 -1681
  157. nltk-3.3/nltk/parse/corenlp.py +780 -0
  158. {nltk-3.2 → nltk-3.3}/nltk/parse/dependencygraph.py +760 -758
  159. {nltk-3.2 → nltk-3.3}/nltk/parse/earleychart.py +452 -451
  160. {nltk-3.2 → nltk-3.3}/nltk/parse/evaluate.py +129 -129
  161. {nltk-3.2 → nltk-3.3}/nltk/parse/featurechart.py +580 -578
  162. {nltk-3.2 → nltk-3.3}/nltk/parse/generate.py +87 -76
  163. {nltk-3.2 → nltk-3.3}/nltk/parse/malt.py +356 -356
  164. {nltk-3.2 → nltk-3.3}/nltk/parse/nonprojectivedependencyparser.py +783 -783
  165. {nltk-3.2 → nltk-3.3}/nltk/parse/pchart.py +522 -522
  166. {nltk-3.2 → nltk-3.3}/nltk/parse/projectivedependencyparser.py +579 -578
  167. {nltk-3.2 → nltk-3.3}/nltk/parse/recursivedescent.py +655 -656
  168. {nltk-3.2 → nltk-3.3}/nltk/parse/shiftreduce.py +458 -459
  169. {nltk-3.2 → nltk-3.3}/nltk/parse/stanford.py +431 -406
  170. {nltk-3.2 → nltk-3.3}/nltk/parse/transitionparser.py +774 -772
  171. {nltk-3.2 → nltk-3.3}/nltk/parse/util.py +231 -231
  172. {nltk-3.2 → nltk-3.3}/nltk/parse/viterbi.py +401 -401
  173. {nltk-3.2 → nltk-3.3}/nltk/probability.py +2410 -2355
  174. {nltk-3.2 → nltk-3.3}/nltk/sem/__init__.py +61 -61
  175. {nltk-3.2 → nltk-3.3}/nltk/sem/boxer.py +1261 -1261
  176. {nltk-3.2 → nltk-3.3}/nltk/sem/chat80.py +782 -782
  177. {nltk-3.2 → nltk-3.3}/nltk/sem/cooper_storage.py +118 -118
  178. {nltk-3.2 → nltk-3.3}/nltk/sem/drt.py +1258 -1257
  179. {nltk-3.2 → nltk-3.3}/nltk/sem/drt_glue_demo.py +485 -489
  180. {nltk-3.2 → nltk-3.3}/nltk/sem/evaluate.py +790 -784
  181. {nltk-3.2 → nltk-3.3}/nltk/sem/glue.py +696 -694
  182. {nltk-3.2 → nltk-3.3}/nltk/sem/hole.py +386 -384
  183. {nltk-3.2 → nltk-3.3}/nltk/sem/lfg.py +210 -208
  184. {nltk-3.2 → nltk-3.3}/nltk/sem/linearlogic.py +451 -449
  185. {nltk-3.2 → nltk-3.3}/nltk/sem/logic.py +1910 -1910
  186. {nltk-3.2 → nltk-3.3}/nltk/sem/relextract.py +476 -483
  187. {nltk-3.2 → nltk-3.3}/nltk/sem/skolemize.py +101 -101
  188. {nltk-3.2 → nltk-3.3}/nltk/sem/util.py +249 -249
  189. {nltk-3.2 → nltk-3.3}/nltk/sentiment/__init__.py +14 -14
  190. {nltk-3.2 → nltk-3.3}/nltk/sentiment/sentiment_analyzer.py +229 -229
  191. {nltk-3.2 → nltk-3.3}/nltk/sentiment/util.py +762 -752
  192. {nltk-3.2 → nltk-3.3}/nltk/sentiment/vader.py +443 -445
  193. {nltk-3.2 → nltk-3.3}/nltk/stem/__init__.py +31 -33
  194. {nltk-3.2 → nltk-3.3}/nltk/stem/api.py +28 -25
  195. nltk-3.3/nltk/stem/arlstem.py +369 -0
  196. {nltk-3.2 → nltk-3.3}/nltk/stem/isri.py +345 -345
  197. {nltk-3.2 → nltk-3.3}/nltk/stem/lancaster.py +337 -310
  198. nltk-3.3/nltk/stem/porter.py +710 -0
  199. {nltk-3.2 → nltk-3.3}/nltk/stem/regexp.py +61 -61
  200. {nltk-3.2 → nltk-3.3}/nltk/stem/rslp.py +142 -142
  201. {nltk-3.2 → nltk-3.3}/nltk/stem/snowball.py +4236 -3712
  202. {nltk-3.2 → nltk-3.3}/nltk/stem/util.py +22 -12
  203. {nltk-3.2 → nltk-3.3}/nltk/stem/wordnet.py +51 -51
  204. {nltk-3.2 → nltk-3.3}/nltk/tag/__init__.py +152 -127
  205. {nltk-3.2 → nltk-3.3}/nltk/tag/api.py +86 -81
  206. {nltk-3.2 → nltk-3.3}/nltk/tag/brill.py +424 -426
  207. {nltk-3.2 → nltk-3.3}/nltk/tag/brill_trainer.py +608 -608
  208. {nltk-3.2 → nltk-3.3}/nltk/tag/crf.py +204 -200
  209. {nltk-3.2 → nltk-3.3}/nltk/tag/hmm.py +1277 -1277
  210. {nltk-3.2 → nltk-3.3}/nltk/tag/hunpos.py +132 -132
  211. {nltk-3.2 → nltk-3.3}/nltk/tag/mapping.py +101 -101
  212. {nltk-3.2 → nltk-3.3}/nltk/tag/perceptron.py +329 -314
  213. {nltk-3.2 → nltk-3.3}/nltk/tag/senna.py +147 -145
  214. {nltk-3.2 → nltk-3.3}/nltk/tag/sequential.py +740 -736
  215. {nltk-3.2 → nltk-3.3}/nltk/tag/stanford.py +219 -196
  216. {nltk-3.2 → nltk-3.3}/nltk/tag/tnt.py +595 -604
  217. {nltk-3.2 → nltk-3.3}/nltk/tag/util.py +72 -72
  218. {nltk-3.2 → nltk-3.3}/nltk/tbl/__init__.py +28 -28
  219. {nltk-3.2 → nltk-3.3}/nltk/tbl/api.py +1 -1
  220. {nltk-3.2 → nltk-3.3}/nltk/tbl/demo.py +366 -366
  221. {nltk-3.2 → nltk-3.3}/nltk/tbl/erroranalysis.py +39 -39
  222. {nltk-3.2 → nltk-3.3}/nltk/tbl/feature.py +259 -261
  223. {nltk-3.2 → nltk-3.3}/nltk/tbl/rule.py +321 -321
  224. {nltk-3.2 → nltk-3.3}/nltk/tbl/template.py +303 -308
  225. {nltk-3.2 → nltk-3.3}/nltk/test/__init__.py +18 -18
  226. {nltk-3.2 → nltk-3.3}/nltk/test/all.py +24 -23
  227. {nltk-3.2 → nltk-3.3}/nltk/test/bleu.doctest +14 -14
  228. {nltk-3.2 → nltk-3.3}/nltk/test/bnc.doctest +60 -60
  229. {nltk-3.2 → nltk-3.3}/nltk/test/ccg.doctest +376 -395
  230. nltk-3.3/nltk/test/ccg_semantics.doctest +553 -0
  231. {nltk-3.2 → nltk-3.3}/nltk/test/chat80.doctest +234 -234
  232. {nltk-3.2 → nltk-3.3}/nltk/test/childes.doctest +184 -184
  233. {nltk-3.2 → nltk-3.3}/nltk/test/childes_fixt.py +14 -13
  234. {nltk-3.2 → nltk-3.3}/nltk/test/chunk.doctest +373 -373
  235. {nltk-3.2 → nltk-3.3}/nltk/test/classify.doctest +185 -185
  236. {nltk-3.2 → nltk-3.3}/nltk/test/classify_fixt.py +11 -10
  237. nltk-3.3/nltk/test/collections.doctest +20 -0
  238. {nltk-3.2 → nltk-3.3}/nltk/test/collocations.doctest +276 -276
  239. {nltk-3.2 → nltk-3.3}/nltk/test/compat.doctest +134 -138
  240. {nltk-3.2 → nltk-3.3}/nltk/test/compat_fixt.py +9 -8
  241. nltk-3.3/nltk/test/concordance.doctest +55 -0
  242. {nltk-3.2 → nltk-3.3}/nltk/test/corpus.doctest +2200 -2212
  243. {nltk-3.2 → nltk-3.3}/nltk/test/corpus_fixt.py +3 -3
  244. {nltk-3.2 → nltk-3.3}/nltk/test/crubadan.doctest +65 -65
  245. {nltk-3.2 → nltk-3.3}/nltk/test/data.doctest +379 -379
  246. {nltk-3.2 → nltk-3.3}/nltk/test/dependency.doctest +241 -241
  247. {nltk-3.2 → nltk-3.3}/nltk/test/discourse.doctest +546 -546
  248. {nltk-3.2 → nltk-3.3}/nltk/test/discourse_fixt.py +14 -13
  249. {nltk-3.2 → nltk-3.3}/nltk/test/doctest_nose_plugin.py +159 -156
  250. {nltk-3.2 → nltk-3.3}/nltk/test/drt.doctest +517 -517
  251. {nltk-3.2 → nltk-3.3}/nltk/test/featgram.doctest +607 -607
  252. {nltk-3.2 → nltk-3.3}/nltk/test/featstruct.doctest +1229 -1230
  253. {nltk-3.2 → nltk-3.3}/nltk/test/framenet.doctest +288 -239
  254. {nltk-3.2 → nltk-3.3}/nltk/test/generate.doctest +67 -67
  255. {nltk-3.2 → nltk-3.3}/nltk/test/gensim.doctest +140 -141
  256. {nltk-3.2 → nltk-3.3}/nltk/test/gensim_fixt.py +10 -9
  257. {nltk-3.2 → nltk-3.3}/nltk/test/gluesemantics.doctest +384 -386
  258. {nltk-3.2 → nltk-3.3}/nltk/test/gluesemantics_malt.doctest +68 -68
  259. {nltk-3.2 → nltk-3.3}/nltk/test/gluesemantics_malt_fixt.py +12 -11
  260. {nltk-3.2 → nltk-3.3}/nltk/test/grammar.doctest +48 -48
  261. {nltk-3.2 → nltk-3.3}/nltk/test/grammartestsuites.doctest +109 -109
  262. {nltk-3.2 → nltk-3.3}/nltk/test/index.doctest +100 -100
  263. {nltk-3.2 → nltk-3.3}/nltk/test/inference.doctest +534 -534
  264. {nltk-3.2 → nltk-3.3}/nltk/test/inference_fixt.py +12 -11
  265. {nltk-3.2 → nltk-3.3}/nltk/test/internals.doctest +140 -140
  266. {nltk-3.2 → nltk-3.3}/nltk/test/japanese.doctest +48 -48
  267. {nltk-3.2 → nltk-3.3}/nltk/test/logic.doctest +1098 -1098
  268. {nltk-3.2 → nltk-3.3}/nltk/test/metrics.doctest +270 -270
  269. {nltk-3.2 → nltk-3.3}/nltk/test/misc.doctest +118 -118
  270. {nltk-3.2 → nltk-3.3}/nltk/test/nonmonotonic.doctest +286 -286
  271. {nltk-3.2 → nltk-3.3}/nltk/test/nonmonotonic_fixt.py +12 -11
  272. {nltk-3.2 → nltk-3.3}/nltk/test/paice.doctest +35 -35
  273. {nltk-3.2 → nltk-3.3}/nltk/test/parse.doctest +884 -884
  274. {nltk-3.2 → nltk-3.3}/nltk/test/portuguese_en.doctest +565 -565
  275. {nltk-3.2 → nltk-3.3}/nltk/test/portuguese_en_fixt.py +16 -16
  276. {nltk-3.2 → nltk-3.3}/nltk/test/probability.doctest +304 -304
  277. {nltk-3.2 → nltk-3.3}/nltk/test/probability_fixt.py +13 -12
  278. {nltk-3.2 → nltk-3.3}/nltk/test/propbank.doctest +176 -176
  279. {nltk-3.2 → nltk-3.3}/nltk/test/relextract.doctest +263 -263
  280. {nltk-3.2 → nltk-3.3}/nltk/test/resolution.doctest +221 -221
  281. {nltk-3.2 → nltk-3.3}/nltk/test/runtests.py +86 -64
  282. {nltk-3.2 → nltk-3.3}/nltk/test/segmentation_fixt.py +10 -10
  283. {nltk-3.2 → nltk-3.3}/nltk/test/semantics.doctest +665 -665
  284. {nltk-3.2 → nltk-3.3}/nltk/test/semantics_fixt.py +7 -7
  285. {nltk-3.2 → nltk-3.3}/nltk/test/sentiment.doctest +233 -233
  286. {nltk-3.2 → nltk-3.3}/nltk/test/sentiwordnet.doctest +41 -41
  287. {nltk-3.2 → nltk-3.3}/nltk/test/simple.doctest +85 -85
  288. {nltk-3.2 → nltk-3.3}/nltk/test/stem.doctest +78 -78
  289. {nltk-3.2 → nltk-3.3}/nltk/test/tag.doctest +33 -33
  290. {nltk-3.2 → nltk-3.3}/nltk/test/tokenize.doctest +273 -166
  291. {nltk-3.2 → nltk-3.3}/nltk/test/toolbox.doctest +307 -307
  292. {nltk-3.2 → nltk-3.3}/nltk/test/translate.doctest +242 -242
  293. {nltk-3.2 → nltk-3.3}/nltk/test/translate_fixt.py +3 -3
  294. {nltk-3.2 → nltk-3.3}/nltk/test/tree.doctest +1101 -1101
  295. {nltk-3.2 → nltk-3.3}/nltk/test/treeprettyprinter.doctest +127 -127
  296. {nltk-3.2 → nltk-3.3}/nltk/test/treetransforms.doctest +156 -156
  297. nltk-3.3/nltk/test/unit/test_2x_compat.py +63 -0
  298. nltk-3.3/nltk/test/unit/test_aline.py +52 -0
  299. nltk-3.3/nltk/test/unit/test_chunk.py +56 -0
  300. {nltk-3.2 → nltk-3.3}/nltk/test/unit/test_classify.py +55 -53
  301. {nltk-3.2 → nltk-3.3}/nltk/test/unit/test_collocations.py +88 -79
  302. nltk-3.3/nltk/test/unit/test_concordance.py +98 -0
  303. nltk-3.3/nltk/test/unit/test_corenlp.py +1000 -0
  304. {nltk-3.2 → nltk-3.3}/nltk/test/unit/test_corpora.py +200 -183
  305. {nltk-3.2 → nltk-3.3}/nltk/test/unit/test_corpus_views.py +45 -45
  306. {nltk-3.2 → nltk-3.3}/nltk/test/unit/test_hmm.py +88 -88
  307. {nltk-3.2 → nltk-3.3}/nltk/test/unit/test_json2csv_corpus.py +188 -187
  308. {nltk-3.2 → nltk-3.3}/nltk/test/unit/test_naivebayes.py +26 -26
  309. nltk-3.3/nltk/test/unit/test_rte_classify.py +86 -0
  310. {nltk-3.2 → nltk-3.3}/nltk/test/unit/test_seekable_unicode_stream_reader.py +124 -124
  311. nltk-3.3/nltk/test/unit/test_senna.py +74 -0
  312. nltk-3.3/nltk/test/unit/test_stem.py +121 -0
  313. {nltk-3.2 → nltk-3.3}/nltk/test/unit/test_tag.py +20 -20
  314. {nltk-3.2 → nltk-3.3}/nltk/test/unit/test_tgrep.py +628 -626
  315. nltk-3.3/nltk/test/unit/test_tokenize.py +168 -0
  316. {nltk-3.2 → nltk-3.3}/nltk/test/unit/test_twitter_auth.py +185 -185
  317. nltk-3.3/nltk/test/unit/test_wordnet.py +134 -0
  318. nltk-3.3/nltk/test/unit/translate/test_bleu.py +244 -0
  319. nltk-3.3/nltk/test/unit/translate/test_gdfa.py +57 -0
  320. {nltk-3.2 → nltk-3.3}/nltk/test/unit/translate/test_ibm1.py +75 -75
  321. {nltk-3.2 → nltk-3.3}/nltk/test/unit/translate/test_ibm2.py +87 -87
  322. {nltk-3.2 → nltk-3.3}/nltk/test/unit/translate/test_ibm3.py +105 -105
  323. {nltk-3.2 → nltk-3.3}/nltk/test/unit/translate/test_ibm4.py +126 -126
  324. {nltk-3.2 → nltk-3.3}/nltk/test/unit/translate/test_ibm5.py +166 -166
  325. {nltk-3.2 → nltk-3.3}/nltk/test/unit/translate/test_ibm_model.py +270 -270
  326. nltk-3.3/nltk/test/unit/translate/test_nist.py +37 -0
  327. {nltk-3.2 → nltk-3.3}/nltk/test/unit/translate/test_stack_decoder.py +300 -300
  328. {nltk-3.2 → nltk-3.3}/nltk/test/unit/utils.py +41 -41
  329. {nltk-3.2 → nltk-3.3}/nltk/test/util.doctest +48 -48
  330. {nltk-3.2 → nltk-3.3}/nltk/test/wordnet.doctest +595 -581
  331. {nltk-3.2 → nltk-3.3}/nltk/test/wordnet_fixt.py +7 -6
  332. {nltk-3.2 → nltk-3.3}/nltk/test/wordnet_lch.doctest +53 -53
  333. {nltk-3.2 → nltk-3.3}/nltk/test/wsd.doctest +68 -68
  334. {nltk-3.2 → nltk-3.3}/nltk/text.py +663 -610
  335. {nltk-3.2 → nltk-3.3}/nltk/tgrep.py +938 -937
  336. {nltk-3.2 → nltk-3.3}/nltk/tokenize/__init__.py +130 -107
  337. {nltk-3.2 → nltk-3.3}/nltk/tokenize/api.py +77 -78
  338. {nltk-3.2 → nltk-3.3}/nltk/tokenize/casual.py +343 -342
  339. {nltk-3.2 → nltk-3.3}/nltk/tokenize/mwe.py +120 -120
  340. nltk-3.3/nltk/tokenize/nist.py +173 -0
  341. {nltk-3.2 → nltk-3.3}/nltk/tokenize/punkt.py +1620 -1601
  342. {nltk-3.2 → nltk-3.3}/nltk/tokenize/regexp.py +208 -202
  343. nltk-3.3/nltk/tokenize/repp.py +151 -0
  344. {nltk-3.2 → nltk-3.3}/nltk/tokenize/sexpr.py +140 -142
  345. {nltk-3.2 → nltk-3.3}/nltk/tokenize/simple.py +138 -136
  346. {nltk-3.2 → nltk-3.3}/nltk/tokenize/stanford.py +117 -113
  347. nltk-3.3/nltk/tokenize/stanford_segmenter.py +246 -0
  348. {nltk-3.2 → nltk-3.3}/nltk/tokenize/texttiling.py +458 -460
  349. nltk-3.3/nltk/tokenize/toktok.py +155 -0
  350. nltk-3.3/nltk/tokenize/treebank.py +363 -0
  351. nltk-3.3/nltk/tokenize/util.py +261 -0
  352. {nltk-3.2 → nltk-3.3}/nltk/toolbox.py +499 -497
  353. {nltk-3.2 → nltk-3.3}/nltk/translate/__init__.py +24 -24
  354. {nltk-3.2 → nltk-3.3}/nltk/translate/api.py +331 -321
  355. {nltk-3.2 → nltk-3.3}/nltk/translate/bleu_score.py +615 -556
  356. nltk-3.3/nltk/translate/chrf_score.py +137 -0
  357. {nltk-3.2 → nltk-3.3}/nltk/translate/gale_church.py +248 -235
  358. {nltk-3.2 → nltk-3.3}/nltk/translate/gdfa.py +135 -131
  359. nltk-3.3/nltk/translate/gleu_score.py +193 -0
  360. {nltk-3.2 → nltk-3.3}/nltk/translate/ibm1.py +250 -241
  361. {nltk-3.2 → nltk-3.3}/nltk/translate/ibm2.py +308 -308
  362. {nltk-3.2 → nltk-3.3}/nltk/translate/ibm3.py +337 -337
  363. {nltk-3.2 → nltk-3.3}/nltk/translate/ibm4.py +467 -467
  364. {nltk-3.2 → nltk-3.3}/nltk/translate/ibm5.py +639 -639
  365. {nltk-3.2 → nltk-3.3}/nltk/translate/ibm_model.py +536 -533
  366. {nltk-3.2 → nltk-3.3}/nltk/translate/metrics.py +40 -40
  367. nltk-3.3/nltk/translate/nist_score.py +178 -0
  368. {nltk-3.2 → nltk-3.3}/nltk/translate/phrase_based.py +175 -175
  369. {nltk-3.2 → nltk-3.3}/nltk/translate/ribes_score.py +325 -325
  370. {nltk-3.2 → nltk-3.3}/nltk/translate/stack_decoder.py +499 -495
  371. {nltk-3.2 → nltk-3.3}/nltk/tree.py +1605 -1603
  372. {nltk-3.2 → nltk-3.3}/nltk/treeprettyprinter.py +564 -564
  373. {nltk-3.2 → nltk-3.3}/nltk/treetransforms.py +309 -309
  374. {nltk-3.2 → nltk-3.3}/nltk/twitter/__init__.py +28 -28
  375. {nltk-3.2 → nltk-3.3}/nltk/twitter/api.py +141 -136
  376. {nltk-3.2 → nltk-3.3}/nltk/twitter/common.py +264 -258
  377. {nltk-3.2 → nltk-3.3}/nltk/twitter/twitter_demo.py +288 -288
  378. {nltk-3.2 → nltk-3.3}/nltk/twitter/twitterclient.py +530 -530
  379. {nltk-3.2 → nltk-3.3}/nltk/twitter/util.py +147 -146
  380. nltk-3.3/nltk/util.py +751 -0
  381. {nltk-3.2 → nltk-3.3}/nltk/wsd.py +53 -53
  382. {nltk-3.2 → nltk-3.3/nltk.egg-info}/PKG-INFO +13 -5
  383. {nltk-3.2 → nltk-3.3}/nltk.egg-info/SOURCES.txt +26 -3
  384. nltk-3.3/nltk.egg-info/requires.txt +31 -0
  385. {nltk-3.2 → nltk-3.3}/setup.cfg +0 -1
  386. {nltk-3.2 → nltk-3.3}/setup.py +102 -75
  387. nltk-3.2/nltk/VERSION +0 -1
  388. nltk-3.2/nltk/compat.py +0 -680
  389. nltk-3.2/nltk/corpus/reader/pl196x.py +0 -278
  390. nltk-3.2/nltk/corpus/reader/verbnet.py +0 -408
  391. nltk-3.2/nltk/corpus/reader/wordlist.py +0 -37
  392. nltk-3.2/nltk/sentiment/vader_lexicon.txt +0 -7517
  393. nltk-3.2/nltk/six.py +0 -868
  394. nltk-3.2/nltk/stem/porter.py +0 -692
  395. nltk-3.2/nltk/test/unit/test_2x_compat.py +0 -26
  396. nltk-3.2/nltk/test/unit/test_stem.py +0 -36
  397. nltk-3.2/nltk/test/unit/test_tokenize.py +0 -23
  398. nltk-3.2/nltk/test/unit/translate/test_bleu.py +0 -84
  399. nltk-3.2/nltk/tokenize/treebank.py +0 -124
  400. nltk-3.2/nltk/tokenize/util.py +0 -90
  401. nltk-3.2/nltk/util.py +0 -1364
  402. {nltk-3.2 → nltk-3.3}/nltk/test/unit/__init__.py +0 -0
  403. {nltk-3.2 → nltk-3.3}/nltk/test/unit/translate/__init__.py +0 -0
  404. {nltk-3.2 → nltk-3.3}/nltk.egg-info/dependency_links.txt +0 -0
  405. {nltk-3.2 → nltk-3.3}/nltk.egg-info/not-zip-safe +0 -0
  406. {nltk-3.2 → nltk-3.3}/nltk.egg-info/top_level.txt +0 -0
@@ -1,610 +1,663 @@
1
- # Natural Language Toolkit: Texts
2
- #
3
- # Copyright (C) 2001-2015 NLTK Project
4
- # Author: Steven Bird <stevenbird1@gmail.com>
5
- # Edward Loper <edloper@gmail.com>
6
- # URL: <http://nltk.org/>
7
- # For license information, see LICENSE.TXT
8
-
9
- """
10
- This module brings together a variety of NLTK functionality for
11
- text analysis, and provides simple, interactive interfaces.
12
- Functionality includes: concordancing, collocation discovery,
13
- regular expression search over tokenized strings, and
14
- distributional similarity.
15
- """
16
- from __future__ import print_function, division, unicode_literals
17
-
18
- from math import log
19
- from collections import defaultdict
20
- from functools import reduce
21
- from itertools import islice
22
- import re
23
-
24
- from nltk.probability import FreqDist, LidstoneProbDist
25
- from nltk.probability import ConditionalFreqDist as CFD
26
- from nltk.util import tokenwrap, LazyConcatenation
27
- from nltk.metrics import f_measure, BigramAssocMeasures
28
- from nltk.collocations import BigramCollocationFinder
29
- from nltk.compat import python_2_unicode_compatible, text_type, Counter
30
-
31
-
32
- class ContextIndex(object):
33
- """
34
- A bidirectional index between words and their 'contexts' in a text.
35
- The context of a word is usually defined to be the words that occur
36
- in a fixed window around the word; but other definitions may also
37
- be used by providing a custom context function.
38
- """
39
- @staticmethod
40
- def _default_context(tokens, i):
41
- """One left token and one right token, normalized to lowercase"""
42
- left = (tokens[i-1].lower() if i != 0 else '*START*')
43
- right = (tokens[i+1].lower() if i != len(tokens) - 1 else '*END*')
44
- return (left, right)
45
-
46
- def __init__(self, tokens, context_func=None, filter=None, key=lambda x:x):
47
- self._key = key
48
- self._tokens = tokens
49
- if context_func:
50
- self._context_func = context_func
51
- else:
52
- self._context_func = self._default_context
53
- if filter:
54
- tokens = [t for t in tokens if filter(t)]
55
- self._word_to_contexts = CFD((self._key(w), self._context_func(tokens, i))
56
- for i, w in enumerate(tokens))
57
- self._context_to_words = CFD((self._context_func(tokens, i), self._key(w))
58
- for i, w in enumerate(tokens))
59
-
60
- def tokens(self):
61
- """
62
- :rtype: list(str)
63
- :return: The document that this context index was
64
- created from.
65
- """
66
- return self._tokens
67
-
68
- def word_similarity_dict(self, word):
69
- """
70
- Return a dictionary mapping from words to 'similarity scores,'
71
- indicating how often these two words occur in the same
72
- context.
73
- """
74
- word = self._key(word)
75
- word_contexts = set(self._word_to_contexts[word])
76
-
77
- scores = {}
78
- for w, w_contexts in self._word_to_contexts.items():
79
- scores[w] = f_measure(word_contexts, set(w_contexts))
80
-
81
- return scores
82
-
83
- def similar_words(self, word, n=20):
84
- scores = defaultdict(int)
85
- for c in self._word_to_contexts[self._key(word)]:
86
- for w in self._context_to_words[c]:
87
- if w != word:
88
- scores[w] += self._context_to_words[c][word] * self._context_to_words[c][w]
89
- return sorted(scores, key=scores.get, reverse=True)[:n]
90
-
91
- def common_contexts(self, words, fail_on_unknown=False):
92
- """
93
- Find contexts where the specified words can all appear; and
94
- return a frequency distribution mapping each context to the
95
- number of times that context was used.
96
-
97
- :param words: The words used to seed the similarity search
98
- :type words: str
99
- :param fail_on_unknown: If true, then raise a value error if
100
- any of the given words do not occur at all in the index.
101
- """
102
- words = [self._key(w) for w in words]
103
- contexts = [set(self._word_to_contexts[w]) for w in words]
104
- empty = [words[i] for i in range(len(words)) if not contexts[i]]
105
- common = reduce(set.intersection, contexts)
106
- if empty and fail_on_unknown:
107
- raise ValueError("The following word(s) were not found:",
108
- " ".join(words))
109
- elif not common:
110
- # nothing in common -- just return an empty freqdist.
111
- return FreqDist()
112
- else:
113
- fd = FreqDist(c for w in words
114
- for c in self._word_to_contexts[w]
115
- if c in common)
116
- return fd
117
-
118
- @python_2_unicode_compatible
119
- class ConcordanceIndex(object):
120
- """
121
- An index that can be used to look up the offset locations at which
122
- a given word occurs in a document.
123
- """
124
- def __init__(self, tokens, key=lambda x:x):
125
- """
126
- Construct a new concordance index.
127
-
128
- :param tokens: The document (list of tokens) that this
129
- concordance index was created from. This list can be used
130
- to access the context of a given word occurrence.
131
- :param key: A function that maps each token to a normalized
132
- version that will be used as a key in the index. E.g., if
133
- you use ``key=lambda s:s.lower()``, then the index will be
134
- case-insensitive.
135
- """
136
- self._tokens = tokens
137
- """The document (list of tokens) that this concordance index
138
- was created from."""
139
-
140
- self._key = key
141
- """Function mapping each token to an index key (or None)."""
142
-
143
- self._offsets = defaultdict(list)
144
- """Dictionary mapping words (or keys) to lists of offset
145
- indices."""
146
-
147
- # Initialize the index (self._offsets)
148
- for index, word in enumerate(tokens):
149
- word = self._key(word)
150
- self._offsets[word].append(index)
151
-
152
- def tokens(self):
153
- """
154
- :rtype: list(str)
155
- :return: The document that this concordance index was
156
- created from.
157
- """
158
- return self._tokens
159
-
160
- def offsets(self, word):
161
- """
162
- :rtype: list(int)
163
- :return: A list of the offset positions at which the given
164
- word occurs. If a key function was specified for the
165
- index, then given word's key will be looked up.
166
- """
167
- word = self._key(word)
168
- return self._offsets[word]
169
-
170
- def __repr__(self):
171
- return '<ConcordanceIndex for %d tokens (%d types)>' % (
172
- len(self._tokens), len(self._offsets))
173
-
174
- def print_concordance(self, word, width=75, lines=25):
175
- """
176
- Print a concordance for ``word`` with the specified context window.
177
-
178
- :param word: The target word
179
- :type word: str
180
- :param width: The width of each line, in characters (default=80)
181
- :type width: int
182
- :param lines: The number of lines to display (default=25)
183
- :type lines: int
184
- """
185
- half_width = (width - len(word) - 2) // 2
186
- context = width // 4 # approx number of words of context
187
-
188
- offsets = self.offsets(word)
189
- if offsets:
190
- lines = min(lines, len(offsets))
191
- print("Displaying %s of %s matches:" % (lines, len(offsets)))
192
- for i in offsets:
193
- if lines <= 0:
194
- break
195
- left = (' ' * half_width +
196
- ' '.join(self._tokens[i-context:i]))
197
- right = ' '.join(self._tokens[i+1:i+context])
198
- left = left[-half_width:]
199
- right = right[:half_width]
200
- print(left, self._tokens[i], right)
201
- lines -= 1
202
- else:
203
- print("No matches")
204
-
205
- class TokenSearcher(object):
206
- """
207
- A class that makes it easier to use regular expressions to search
208
- over tokenized strings. The tokenized string is converted to a
209
- string where tokens are marked with angle brackets -- e.g.,
210
- ``'<the><window><is><still><open>'``. The regular expression
211
- passed to the ``findall()`` method is modified to treat angle
212
- brackets as non-capturing parentheses, in addition to matching the
213
- token boundaries; and to have ``'.'`` not match the angle brackets.
214
- """
215
- def __init__(self, tokens):
216
- self._raw = ''.join('<'+w+'>' for w in tokens)
217
-
218
- def findall(self, regexp):
219
- """
220
- Find instances of the regular expression in the text.
221
- The text is a list of tokens, and a regexp pattern to match
222
- a single token must be surrounded by angle brackets. E.g.
223
-
224
- >>> from nltk.text import TokenSearcher
225
- >>> print('hack'); from nltk.book import text1, text5, text9
226
- hack...
227
- >>> text5.findall("<.*><.*><bro>")
228
- you rule bro; telling you bro; u twizted bro
229
- >>> text1.findall("<a>(<.*>)<man>")
230
- monied; nervous; dangerous; white; white; white; pious; queer; good;
231
- mature; white; Cape; great; wise; wise; butterless; white; fiendish;
232
- pale; furious; better; certain; complete; dismasted; younger; brave;
233
- brave; brave; brave
234
- >>> text9.findall("<th.*>{3,}")
235
- thread through those; the thought that; that the thing; the thing
236
- that; that that thing; through these than through; them that the;
237
- through the thick; them that they; thought that the
238
-
239
- :param regexp: A regular expression
240
- :type regexp: str
241
- """
242
- # preprocess the regular expression
243
- regexp = re.sub(r'\s', '', regexp)
244
- regexp = re.sub(r'<', '(?:<(?:', regexp)
245
- regexp = re.sub(r'>', ')>)', regexp)
246
- regexp = re.sub(r'(?<!\\)\.', '[^>]', regexp)
247
-
248
- # perform the search
249
- hits = re.findall(regexp, self._raw)
250
-
251
- # Sanity check
252
- for h in hits:
253
- if not h.startswith('<') and h.endswith('>'):
254
- raise ValueError('Bad regexp for TokenSearcher.findall')
255
-
256
- # postprocess the output
257
- hits = [h[1:-1].split('><') for h in hits]
258
- return hits
259
-
260
-
261
- @python_2_unicode_compatible
262
- class Text(object):
263
- """
264
- A wrapper around a sequence of simple (string) tokens, which is
265
- intended to support initial exploration of texts (via the
266
- interactive console). Its methods perform a variety of analyses
267
- on the text's contexts (e.g., counting, concordancing, collocation
268
- discovery), and display the results. If you wish to write a
269
- program which makes use of these analyses, then you should bypass
270
- the ``Text`` class, and use the appropriate analysis function or
271
- class directly instead.
272
-
273
- A ``Text`` is typically initialized from a given document or
274
- corpus. E.g.:
275
-
276
- >>> import nltk.corpus
277
- >>> from nltk.text import Text
278
- >>> moby = Text(nltk.corpus.gutenberg.words('melville-moby_dick.txt'))
279
-
280
- """
281
- # This defeats lazy loading, but makes things faster. This
282
- # *shouldn't* be necessary because the corpus view *should* be
283
- # doing intelligent caching, but without this it's running slow.
284
- # Look into whether the caching is working correctly.
285
- _COPY_TOKENS = True
286
-
287
- def __init__(self, tokens, name=None):
288
- """
289
- Create a Text object.
290
-
291
- :param tokens: The source text.
292
- :type tokens: sequence of str
293
- """
294
- if self._COPY_TOKENS:
295
- tokens = list(tokens)
296
- self.tokens = tokens
297
-
298
- if name:
299
- self.name = name
300
- elif ']' in tokens[:20]:
301
- end = tokens[:20].index(']')
302
- self.name = " ".join(text_type(tok) for tok in tokens[1:end])
303
- else:
304
- self.name = " ".join(text_type(tok) for tok in tokens[:8]) + "..."
305
-
306
- #////////////////////////////////////////////////////////////
307
- # Support item & slice access
308
- #////////////////////////////////////////////////////////////
309
-
310
- def __getitem__(self, i):
311
- if isinstance(i, slice):
312
- return self.tokens[i.start:i.stop]
313
- else:
314
- return self.tokens[i]
315
-
316
- def __len__(self):
317
- return len(self.tokens)
318
-
319
- #////////////////////////////////////////////////////////////
320
- # Interactive console methods
321
- #////////////////////////////////////////////////////////////
322
-
323
- def concordance(self, word, width=79, lines=25):
324
- """
325
- Print a concordance for ``word`` with the specified context window.
326
- Word matching is not case-sensitive.
327
- :seealso: ``ConcordanceIndex``
328
- """
329
- if '_concordance_index' not in self.__dict__:
330
- #print("Building index...")
331
- self._concordance_index = ConcordanceIndex(self.tokens,
332
- key=lambda s:s.lower())
333
-
334
- self._concordance_index.print_concordance(word, width, lines)
335
-
336
- def collocations(self, num=20, window_size=2):
337
- """
338
- Print collocations derived from the text, ignoring stopwords.
339
-
340
- :seealso: find_collocations
341
- :param num: The maximum number of collocations to print.
342
- :type num: int
343
- :param window_size: The number of tokens spanned by a collocation (default=2)
344
- :type window_size: int
345
- """
346
- if not ('_collocations' in self.__dict__ and self._num == num and self._window_size == window_size):
347
- self._num = num
348
- self._window_size = window_size
349
-
350
- #print("Building collocations list")
351
- from nltk.corpus import stopwords
352
- ignored_words = stopwords.words('english')
353
- finder = BigramCollocationFinder.from_words(self.tokens, window_size)
354
- finder.apply_freq_filter(2)
355
- finder.apply_word_filter(lambda w: len(w) < 3 or w.lower() in ignored_words)
356
- bigram_measures = BigramAssocMeasures()
357
- self._collocations = finder.nbest(bigram_measures.likelihood_ratio, num)
358
- colloc_strings = [w1+' '+w2 for w1, w2 in self._collocations]
359
- print(tokenwrap(colloc_strings, separator="; "))
360
-
361
- def count(self, word):
362
- """
363
- Count the number of times this word appears in the text.
364
- """
365
- return self.tokens.count(word)
366
-
367
- def index(self, word):
368
- """
369
- Find the index of the first occurrence of the word in the text.
370
- """
371
- return self.tokens.index(word)
372
-
373
- def readability(self, method):
374
- # code from nltk_contrib.readability
375
- raise NotImplementedError
376
-
377
- def similar(self, word, num=20):
378
- """
379
- Distributional similarity: find other words which appear in the
380
- same contexts as the specified word; list most similar words first.
381
-
382
- :param word: The word used to seed the similarity search
383
- :type word: str
384
- :param num: The number of words to generate (default=20)
385
- :type num: int
386
- :seealso: ContextIndex.similar_words()
387
- """
388
- if '_word_context_index' not in self.__dict__:
389
- #print('Building word-context index...')
390
- self._word_context_index = ContextIndex(self.tokens,
391
- filter=lambda x:x.isalpha(),
392
- key=lambda s:s.lower())
393
-
394
- # words = self._word_context_index.similar_words(word, num)
395
-
396
- word = word.lower()
397
- wci = self._word_context_index._word_to_contexts
398
- if word in wci.conditions():
399
- contexts = set(wci[word])
400
- fd = Counter(w for w in wci.conditions() for c in wci[w]
401
- if c in contexts and not w == word)
402
- words = [w for w, _ in fd.most_common(num)]
403
- print(tokenwrap(words))
404
- else:
405
- print("No matches")
406
-
407
-
408
- def common_contexts(self, words, num=20):
409
- """
410
- Find contexts where the specified words appear; list
411
- most frequent common contexts first.
412
-
413
- :param word: The word used to seed the similarity search
414
- :type word: str
415
- :param num: The number of words to generate (default=20)
416
- :type num: int
417
- :seealso: ContextIndex.common_contexts()
418
- """
419
- if '_word_context_index' not in self.__dict__:
420
- #print('Building word-context index...')
421
- self._word_context_index = ContextIndex(self.tokens,
422
- key=lambda s:s.lower())
423
-
424
- try:
425
- fd = self._word_context_index.common_contexts(words, True)
426
- if not fd:
427
- print("No common contexts were found")
428
- else:
429
- ranked_contexts = [w for w, _ in fd.most_common(num)]
430
- print(tokenwrap(w1+"_"+w2 for w1,w2 in ranked_contexts))
431
-
432
- except ValueError as e:
433
- print(e)
434
-
435
- def dispersion_plot(self, words):
436
- """
437
- Produce a plot showing the distribution of the words through the text.
438
- Requires pylab to be installed.
439
-
440
- :param words: The words to be plotted
441
- :type words: list(str)
442
- :seealso: nltk.draw.dispersion_plot()
443
- """
444
- from nltk.draw import dispersion_plot
445
- dispersion_plot(self, words)
446
-
447
- def plot(self, *args):
448
- """
449
- See documentation for FreqDist.plot()
450
- :seealso: nltk.prob.FreqDist.plot()
451
- """
452
- self.vocab().plot(*args)
453
-
454
- def vocab(self):
455
- """
456
- :seealso: nltk.prob.FreqDist
457
- """
458
- if "_vocab" not in self.__dict__:
459
- #print("Building vocabulary index...")
460
- self._vocab = FreqDist(self)
461
- return self._vocab
462
-
463
- def findall(self, regexp):
464
- """
465
- Find instances of the regular expression in the text.
466
- The text is a list of tokens, and a regexp pattern to match
467
- a single token must be surrounded by angle brackets. E.g.
468
-
469
- >>> print('hack'); from nltk.book import text1, text5, text9
470
- hack...
471
- >>> text5.findall("<.*><.*><bro>")
472
- you rule bro; telling you bro; u twizted bro
473
- >>> text1.findall("<a>(<.*>)<man>")
474
- monied; nervous; dangerous; white; white; white; pious; queer; good;
475
- mature; white; Cape; great; wise; wise; butterless; white; fiendish;
476
- pale; furious; better; certain; complete; dismasted; younger; brave;
477
- brave; brave; brave
478
- >>> text9.findall("<th.*>{3,}")
479
- thread through those; the thought that; that the thing; the thing
480
- that; that that thing; through these than through; them that the;
481
- through the thick; them that they; thought that the
482
-
483
- :param regexp: A regular expression
484
- :type regexp: str
485
- """
486
-
487
- if "_token_searcher" not in self.__dict__:
488
- self._token_searcher = TokenSearcher(self)
489
-
490
- hits = self._token_searcher.findall(regexp)
491
- hits = [' '.join(h) for h in hits]
492
- print(tokenwrap(hits, "; "))
493
-
494
- #////////////////////////////////////////////////////////////
495
- # Helper Methods
496
- #////////////////////////////////////////////////////////////
497
-
498
- _CONTEXT_RE = re.compile('\w+|[\.\!\?]')
499
- def _context(self, tokens, i):
500
- """
501
- One left & one right token, both case-normalized. Skip over
502
- non-sentence-final punctuation. Used by the ``ContextIndex``
503
- that is created for ``similar()`` and ``common_contexts()``.
504
- """
505
- # Left context
506
- j = i-1
507
- while j>=0 and not self._CONTEXT_RE.match(tokens[j]):
508
- j -= 1
509
- left = (tokens[j] if j != 0 else '*START*')
510
-
511
- # Right context
512
- j = i+1
513
- while j<len(tokens) and not self._CONTEXT_RE.match(tokens[j]):
514
- j += 1
515
- right = (tokens[j] if j != len(tokens) else '*END*')
516
-
517
- return (left, right)
518
-
519
- #////////////////////////////////////////////////////////////
520
- # String Display
521
- #////////////////////////////////////////////////////////////
522
-
523
- def __str__(self):
524
- return '<Text: %s>' % self.name
525
-
526
- def __repr__(self):
527
- return '<Text: %s>' % self.name
528
-
529
-
530
- # Prototype only; this approach will be slow to load
531
- class TextCollection(Text):
532
- """A collection of texts, which can be loaded with list of texts, or
533
- with a corpus consisting of one or more texts, and which supports
534
- counting, concordancing, collocation discovery, etc. Initialize a
535
- TextCollection as follows:
536
-
537
- >>> import nltk.corpus
538
- >>> from nltk.text import TextCollection
539
- >>> print('hack'); from nltk.book import text1, text2, text3
540
- hack...
541
- >>> gutenberg = TextCollection(nltk.corpus.gutenberg)
542
- >>> mytexts = TextCollection([text1, text2, text3])
543
-
544
- Iterating over a TextCollection produces all the tokens of all the
545
- texts in order.
546
- """
547
- def __init__(self, source):
548
- if hasattr(source, 'words'): # bridge to the text corpus reader
549
- source = [source.words(f) for f in source.fileids()]
550
-
551
- self._texts = source
552
- Text.__init__(self, LazyConcatenation(source))
553
- self._idf_cache = {}
554
-
555
- def tf(self, term, text):
556
- """ The frequency of the term in text. """
557
- return text.count(term) / len(text)
558
-
559
- def idf(self, term):
560
- """ The number of texts in the corpus divided by the
561
- number of texts that the term appears in.
562
- If a term does not appear in the corpus, 0.0 is returned. """
563
- # idf values are cached for performance.
564
- idf = self._idf_cache.get(term)
565
- if idf is None:
566
- matches = len([True for text in self._texts if term in text])
567
- # FIXME Should this raise some kind of error instead?
568
- idf = (log(len(self._texts) / matches) if matches else 0.0)
569
- self._idf_cache[term] = idf
570
- return idf
571
-
572
- def tf_idf(self, term, text):
573
- return self.tf(term, text) * self.idf(term)
574
-
575
- def demo():
576
- from nltk.corpus import brown
577
- text = Text(brown.words(categories='news'))
578
- print(text)
579
- print()
580
- print("Concordance:")
581
- text.concordance('news')
582
- print()
583
- print("Distributionally similar words:")
584
- text.similar('news')
585
- print()
586
- print("Collocations:")
587
- text.collocations()
588
- print()
589
- #print("Automatically generated text:")
590
- #text.generate()
591
- #print()
592
- print("Dispersion plot:")
593
- text.dispersion_plot(['news', 'report', 'said', 'announced'])
594
- print()
595
- print("Vocabulary plot:")
596
- text.plot(50)
597
- print()
598
- print("Indexing:")
599
- print("text[3]:", text[3])
600
- print("text[3:5]:", text[3:5])
601
- print("text.vocab()['news']:", text.vocab()['news'])
602
-
603
- if __name__ == '__main__':
604
- demo()
605
-
606
- __all__ = ["ContextIndex",
607
- "ConcordanceIndex",
608
- "TokenSearcher",
609
- "Text",
610
- "TextCollection"]
1
+ # Natural Language Toolkit: Texts
2
+ #
3
+ # Copyright (C) 2001-2018 NLTK Project
4
+ # Author: Steven Bird <stevenbird1@gmail.com>
5
+ # Edward Loper <edloper@gmail.com>
6
+ # URL: <http://nltk.org/>
7
+ # For license information, see LICENSE.TXT
8
+
9
+ """
10
+ This module brings together a variety of NLTK functionality for
11
+ text analysis, and provides simple, interactive interfaces.
12
+ Functionality includes: concordancing, collocation discovery,
13
+ regular expression search over tokenized strings, and
14
+ distributional similarity.
15
+ """
16
+ from __future__ import print_function, division, unicode_literals, absolute_import
17
+
18
+ from math import log
19
+ from collections import defaultdict, Counter, namedtuple
20
+ from functools import reduce
21
+ from itertools import islice
22
+ import re
23
+
24
+ from six import text_type
25
+
26
+ from nltk.probability import FreqDist, LidstoneProbDist
27
+ from nltk.probability import ConditionalFreqDist as CFD
28
+ from nltk.util import tokenwrap, LazyConcatenation
29
+ from nltk.metrics import f_measure, BigramAssocMeasures
30
+ from nltk.collocations import BigramCollocationFinder
31
+ from nltk.compat import python_2_unicode_compatible
32
+
33
+ ConcordanceLine = namedtuple('ConcordanceLine',
34
+ ['left', 'query', 'right', 'offset',
35
+ 'left_print', 'right_print', 'line'])
36
+
37
+ class ContextIndex(object):
38
+ """
39
+ A bidirectional index between words and their 'contexts' in a text.
40
+ The context of a word is usually defined to be the words that occur
41
+ in a fixed window around the word; but other definitions may also
42
+ be used by providing a custom context function.
43
+ """
44
+ @staticmethod
45
+ def _default_context(tokens, i):
46
+ """One left token and one right token, normalized to lowercase"""
47
+ left = (tokens[i-1].lower() if i != 0 else '*START*')
48
+ right = (tokens[i+1].lower() if i != len(tokens) - 1 else '*END*')
49
+ return (left, right)
50
+
51
+ def __init__(self, tokens, context_func=None, filter=None, key=lambda x:x):
52
+ self._key = key
53
+ self._tokens = tokens
54
+ if context_func:
55
+ self._context_func = context_func
56
+ else:
57
+ self._context_func = self._default_context
58
+ if filter:
59
+ tokens = [t for t in tokens if filter(t)]
60
+ self._word_to_contexts = CFD((self._key(w), self._context_func(tokens, i))
61
+ for i, w in enumerate(tokens))
62
+ self._context_to_words = CFD((self._context_func(tokens, i), self._key(w))
63
+ for i, w in enumerate(tokens))
64
+
65
+ def tokens(self):
66
+ """
67
+ :rtype: list(str)
68
+ :return: The document that this context index was
69
+ created from.
70
+ """
71
+ return self._tokens
72
+
73
+ def word_similarity_dict(self, word):
74
+ """
75
+ Return a dictionary mapping from words to 'similarity scores,'
76
+ indicating how often these two words occur in the same
77
+ context.
78
+ """
79
+ word = self._key(word)
80
+ word_contexts = set(self._word_to_contexts[word])
81
+
82
+ scores = {}
83
+ for w, w_contexts in self._word_to_contexts.items():
84
+ scores[w] = f_measure(word_contexts, set(w_contexts))
85
+
86
+ return scores
87
+
88
+ def similar_words(self, word, n=20):
89
+ scores = defaultdict(int)
90
+ for c in self._word_to_contexts[self._key(word)]:
91
+ for w in self._context_to_words[c]:
92
+ if w != word:
93
+ scores[w] += self._context_to_words[c][word] * self._context_to_words[c][w]
94
+ return sorted(scores, key=scores.get, reverse=True)[:n]
95
+
96
+ def common_contexts(self, words, fail_on_unknown=False):
97
+ """
98
+ Find contexts where the specified words can all appear; and
99
+ return a frequency distribution mapping each context to the
100
+ number of times that context was used.
101
+
102
+ :param words: The words used to seed the similarity search
103
+ :type words: str
104
+ :param fail_on_unknown: If true, then raise a value error if
105
+ any of the given words do not occur at all in the index.
106
+ """
107
+ words = [self._key(w) for w in words]
108
+ contexts = [set(self._word_to_contexts[w]) for w in words]
109
+ empty = [words[i] for i in range(len(words)) if not contexts[i]]
110
+ common = reduce(set.intersection, contexts)
111
+ if empty and fail_on_unknown:
112
+ raise ValueError("The following word(s) were not found:",
113
+ " ".join(words))
114
+ elif not common:
115
+ # nothing in common -- just return an empty freqdist.
116
+ return FreqDist()
117
+ else:
118
+ fd = FreqDist(c for w in words
119
+ for c in self._word_to_contexts[w]
120
+ if c in common)
121
+ return fd
122
+
123
+
124
+ @python_2_unicode_compatible
125
+ class ConcordanceIndex(object):
126
+ """
127
+ An index that can be used to look up the offset locations at which
128
+ a given word occurs in a document.
129
+ """
130
+ def __init__(self, tokens, key=lambda x:x):
131
+ """
132
+ Construct a new concordance index.
133
+
134
+ :param tokens: The document (list of tokens) that this
135
+ concordance index was created from. This list can be used
136
+ to access the context of a given word occurrence.
137
+ :param key: A function that maps each token to a normalized
138
+ version that will be used as a key in the index. E.g., if
139
+ you use ``key=lambda s:s.lower()``, then the index will be
140
+ case-insensitive.
141
+ """
142
+ self._tokens = tokens
143
+ """The document (list of tokens) that this concordance index
144
+ was created from."""
145
+
146
+ self._key = key
147
+ """Function mapping each token to an index key (or None)."""
148
+
149
+ self._offsets = defaultdict(list)
150
+ """Dictionary mapping words (or keys) to lists of offset indices."""
151
+ # Initialize the index (self._offsets)
152
+ for index, word in enumerate(tokens):
153
+ word = self._key(word)
154
+ self._offsets[word].append(index)
155
+
156
+ def tokens(self):
157
+ """
158
+ :rtype: list(str)
159
+ :return: The document that this concordance index was
160
+ created from.
161
+ """
162
+ return self._tokens
163
+
164
+ def offsets(self, word):
165
+ """
166
+ :rtype: list(int)
167
+ :return: A list of the offset positions at which the given
168
+ word occurs. If a key function was specified for the
169
+ index, then given word's key will be looked up.
170
+ """
171
+ word = self._key(word)
172
+ return self._offsets[word]
173
+
174
+ def __repr__(self):
175
+ return '<ConcordanceIndex for %d tokens (%d types)>' % (
176
+ len(self._tokens), len(self._offsets))
177
+
178
+ def find_concordance(self, word, width=80, lines=25):
179
+ """
180
+ Find the concordance lines given the query word.
181
+ """
182
+ half_width = (width - len(word) - 2) // 2
183
+ context = width // 4 # approx number of words of context
184
+
185
+ # Find the instances of the word to create the ConcordanceLine
186
+ concordance_list = []
187
+ offsets = self.offsets(word)
188
+ if offsets:
189
+ for i in offsets:
190
+ query_word = self._tokens[i]
191
+ # Find the context of query word.
192
+ left_context = self._tokens[i-context:i]
193
+ right_context = self._tokens[i+1:i+context]
194
+ # Create the pretty lines with the query_word in the middle.
195
+ left_print= ' '.join(left_context)[-half_width:]
196
+ right_print = ' '.join(right_context)[:half_width]
197
+ # The WYSIWYG line of the concordance.
198
+ line_print = ' '.join([left_print, query_word, right_print])
199
+ # Create the ConcordanceLine
200
+ concordance_line = ConcordanceLine(left_context, query_word,
201
+ right_context, i,
202
+ left_print, right_print, line_print)
203
+ concordance_list.append(concordance_line)
204
+ return concordance_list[:lines]
205
+
206
+ def print_concordance(self, word, width=80, lines=25):
207
+ """
208
+ Print concordance lines given the query word.
209
+ :param word: The target word
210
+ :type word: str
211
+ :param lines: The number of lines to display (default=25)
212
+ :type lines: int
213
+ :param width: The width of each line, in characters (default=80)
214
+ :type width: int
215
+ :param save: The option to save the concordance.
216
+ :type save: bool
217
+ """
218
+ concordance_list = self.find_concordance(word, width=80, lines=25)
219
+
220
+ if not concordance_list:
221
+ print("no matches")
222
+ else:
223
+ lines = min(lines, len(concordance_list))
224
+ print("Displaying {} of {} matches:".format(lines,len(concordance_list)))
225
+ for i, concordance_line in enumerate(concordance_list[:lines]):
226
+ print(concordance_line.line)
227
+
228
+
229
+ class TokenSearcher(object):
230
+ """
231
+ A class that makes it easier to use regular expressions to search
232
+ over tokenized strings. The tokenized string is converted to a
233
+ string where tokens are marked with angle brackets -- e.g.,
234
+ ``'<the><window><is><still><open>'``. The regular expression
235
+ passed to the ``findall()`` method is modified to treat angle
236
+ brackets as non-capturing parentheses, in addition to matching the
237
+ token boundaries; and to have ``'.'`` not match the angle brackets.
238
+ """
239
+ def __init__(self, tokens):
240
+ self._raw = ''.join('<'+w+'>' for w in tokens)
241
+
242
+ def findall(self, regexp):
243
+ """
244
+ Find instances of the regular expression in the text.
245
+ The text is a list of tokens, and a regexp pattern to match
246
+ a single token must be surrounded by angle brackets. E.g.
247
+
248
+ >>> from nltk.text import TokenSearcher
249
+ >>> print('hack'); from nltk.book import text1, text5, text9
250
+ hack...
251
+ >>> text5.findall("<.*><.*><bro>")
252
+ you rule bro; telling you bro; u twizted bro
253
+ >>> text1.findall("<a>(<.*>)<man>")
254
+ monied; nervous; dangerous; white; white; white; pious; queer; good;
255
+ mature; white; Cape; great; wise; wise; butterless; white; fiendish;
256
+ pale; furious; better; certain; complete; dismasted; younger; brave;
257
+ brave; brave; brave
258
+ >>> text9.findall("<th.*>{3,}")
259
+ thread through those; the thought that; that the thing; the thing
260
+ that; that that thing; through these than through; them that the;
261
+ through the thick; them that they; thought that the
262
+
263
+ :param regexp: A regular expression
264
+ :type regexp: str
265
+ """
266
+ # preprocess the regular expression
267
+ regexp = re.sub(r'\s', '', regexp)
268
+ regexp = re.sub(r'<', '(?:<(?:', regexp)
269
+ regexp = re.sub(r'>', ')>)', regexp)
270
+ regexp = re.sub(r'(?<!\\)\.', '[^>]', regexp)
271
+
272
+ # perform the search
273
+ hits = re.findall(regexp, self._raw)
274
+
275
+ # Sanity check
276
+ for h in hits:
277
+ if not h.startswith('<') and h.endswith('>'):
278
+ raise ValueError('Bad regexp for TokenSearcher.findall')
279
+
280
+ # postprocess the output
281
+ hits = [h[1:-1].split('><') for h in hits]
282
+ return hits
283
+
284
+
285
+ @python_2_unicode_compatible
286
+ class Text(object):
287
+ """
288
+ A wrapper around a sequence of simple (string) tokens, which is
289
+ intended to support initial exploration of texts (via the
290
+ interactive console). Its methods perform a variety of analyses
291
+ on the text's contexts (e.g., counting, concordancing, collocation
292
+ discovery), and display the results. If you wish to write a
293
+ program which makes use of these analyses, then you should bypass
294
+ the ``Text`` class, and use the appropriate analysis function or
295
+ class directly instead.
296
+
297
+ A ``Text`` is typically initialized from a given document or
298
+ corpus. E.g.:
299
+
300
+ >>> import nltk.corpus
301
+ >>> from nltk.text import Text
302
+ >>> moby = Text(nltk.corpus.gutenberg.words('melville-moby_dick.txt'))
303
+
304
+ """
305
+ # This defeats lazy loading, but makes things faster. This
306
+ # *shouldn't* be necessary because the corpus view *should* be
307
+ # doing intelligent caching, but without this it's running slow.
308
+ # Look into whether the caching is working correctly.
309
+ _COPY_TOKENS = True
310
+
311
+ def __init__(self, tokens, name=None):
312
+ """
313
+ Create a Text object.
314
+
315
+ :param tokens: The source text.
316
+ :type tokens: sequence of str
317
+ """
318
+ if self._COPY_TOKENS:
319
+ tokens = list(tokens)
320
+ self.tokens = tokens
321
+
322
+ if name:
323
+ self.name = name
324
+ elif ']' in tokens[:20]:
325
+ end = tokens[:20].index(']')
326
+ self.name = " ".join(text_type(tok) for tok in tokens[1:end])
327
+ else:
328
+ self.name = " ".join(text_type(tok) for tok in tokens[:8]) + "..."
329
+
330
+ #////////////////////////////////////////////////////////////
331
+ # Support item & slice access
332
+ #////////////////////////////////////////////////////////////
333
+
334
+ def __getitem__(self, i):
335
+ return self.tokens[i]
336
+
337
+ def __len__(self):
338
+ return len(self.tokens)
339
+
340
+ #////////////////////////////////////////////////////////////
341
+ # Interactive console methods
342
+ #////////////////////////////////////////////////////////////
343
+
344
+ def concordance(self, word, width=79, lines=25):
345
+ """
346
+ Prints a concordance for ``word`` with the specified context window.
347
+ Word matching is not case-sensitive.
348
+
349
+ :param word: The target word
350
+ :type word: str
351
+ :param width: The width of each line, in characters (default=80)
352
+ :type width: int
353
+ :param lines: The number of lines to display (default=25)
354
+ :type lines: int
355
+
356
+ :seealso: ``ConcordanceIndex``
357
+ """
358
+ if '_concordance_index' not in self.__dict__:
359
+ self._concordance_index = ConcordanceIndex(self.tokens, key=lambda s:s.lower())
360
+
361
+ return self._concordance_index.print_concordance(word, width, lines)
362
+
363
+ def concordance_list(self, word, width=79, lines=25):
364
+ """
365
+ Generate a concordance for ``word`` with the specified context window.
366
+ Word matching is not case-sensitive.
367
+
368
+ :param word: The target word
369
+ :type word: str
370
+ :param width: The width of each line, in characters (default=80)
371
+ :type width: int
372
+ :param lines: The number of lines to display (default=25)
373
+ :type lines: int
374
+
375
+ :seealso: ``ConcordanceIndex``
376
+ """
377
+ if '_concordance_index' not in self.__dict__:
378
+ self._concordance_index = ConcordanceIndex(self.tokens, key=lambda s:s.lower())
379
+ return self._concordance_index.find_concordance(word, width, lines)
380
+
381
+ def collocations(self, num=20, window_size=2):
382
+ """
383
+ Print collocations derived from the text, ignoring stopwords.
384
+
385
+ :seealso: find_collocations
386
+ :param num: The maximum number of collocations to print.
387
+ :type num: int
388
+ :param window_size: The number of tokens spanned by a collocation (default=2)
389
+ :type window_size: int
390
+ """
391
+ if not ('_collocations' in self.__dict__ and self._num == num and self._window_size == window_size):
392
+ self._num = num
393
+ self._window_size = window_size
394
+
395
+ #print("Building collocations list")
396
+ from nltk.corpus import stopwords
397
+ ignored_words = stopwords.words('english')
398
+ finder = BigramCollocationFinder.from_words(self.tokens, window_size)
399
+ finder.apply_freq_filter(2)
400
+ finder.apply_word_filter(lambda w: len(w) < 3 or w.lower() in ignored_words)
401
+ bigram_measures = BigramAssocMeasures()
402
+ self._collocations = finder.nbest(bigram_measures.likelihood_ratio, num)
403
+ colloc_strings = [w1+' '+w2 for w1, w2 in self._collocations]
404
+ print(tokenwrap(colloc_strings, separator="; "))
405
+
406
+ def count(self, word):
407
+ """
408
+ Count the number of times this word appears in the text.
409
+ """
410
+ return self.tokens.count(word)
411
+
412
+ def index(self, word):
413
+ """
414
+ Find the index of the first occurrence of the word in the text.
415
+ """
416
+ return self.tokens.index(word)
417
+
418
+ def readability(self, method):
419
+ # code from nltk_contrib.readability
420
+ raise NotImplementedError
421
+
422
+ def similar(self, word, num=20):
423
+ """
424
+ Distributional similarity: find other words which appear in the
425
+ same contexts as the specified word; list most similar words first.
426
+
427
+ :param word: The word used to seed the similarity search
428
+ :type word: str
429
+ :param num: The number of words to generate (default=20)
430
+ :type num: int
431
+ :seealso: ContextIndex.similar_words()
432
+ """
433
+ if '_word_context_index' not in self.__dict__:
434
+ #print('Building word-context index...')
435
+ self._word_context_index = ContextIndex(self.tokens,
436
+ filter=lambda x:x.isalpha(),
437
+ key=lambda s:s.lower())
438
+
439
+ # words = self._word_context_index.similar_words(word, num)
440
+
441
+ word = word.lower()
442
+ wci = self._word_context_index._word_to_contexts
443
+ if word in wci.conditions():
444
+ contexts = set(wci[word])
445
+ fd = Counter(w for w in wci.conditions() for c in wci[w]
446
+ if c in contexts and not w == word)
447
+ words = [w for w, _ in fd.most_common(num)]
448
+ print(tokenwrap(words))
449
+ else:
450
+ print("No matches")
451
+
452
+
453
+ def common_contexts(self, words, num=20):
454
+ """
455
+ Find contexts where the specified words appear; list
456
+ most frequent common contexts first.
457
+
458
+ :param word: The word used to seed the similarity search
459
+ :type word: str
460
+ :param num: The number of words to generate (default=20)
461
+ :type num: int
462
+ :seealso: ContextIndex.common_contexts()
463
+ """
464
+ if '_word_context_index' not in self.__dict__:
465
+ #print('Building word-context index...')
466
+ self._word_context_index = ContextIndex(self.tokens,
467
+ key=lambda s:s.lower())
468
+
469
+ try:
470
+ fd = self._word_context_index.common_contexts(words, True)
471
+ if not fd:
472
+ print("No common contexts were found")
473
+ else:
474
+ ranked_contexts = [w for w, _ in fd.most_common(num)]
475
+ print(tokenwrap(w1+"_"+w2 for w1,w2 in ranked_contexts))
476
+
477
+ except ValueError as e:
478
+ print(e)
479
+
480
+ def dispersion_plot(self, words):
481
+ """
482
+ Produce a plot showing the distribution of the words through the text.
483
+ Requires pylab to be installed.
484
+
485
+ :param words: The words to be plotted
486
+ :type words: list(str)
487
+ :seealso: nltk.draw.dispersion_plot()
488
+ """
489
+ from nltk.draw import dispersion_plot
490
+ dispersion_plot(self, words)
491
+
492
+ def generate(self, words):
493
+ """
494
+ Issues a reminder to users following the book online
495
+ """
496
+ import warnings
497
+ warnings.warn('The generate() method is no longer available.', DeprecationWarning)
498
+
499
+ def plot(self, *args):
500
+ """
501
+ See documentation for FreqDist.plot()
502
+ :seealso: nltk.prob.FreqDist.plot()
503
+ """
504
+ self.vocab().plot(*args)
505
+
506
+ def vocab(self):
507
+ """
508
+ :seealso: nltk.prob.FreqDist
509
+ """
510
+ if "_vocab" not in self.__dict__:
511
+ #print("Building vocabulary index...")
512
+ self._vocab = FreqDist(self)
513
+ return self._vocab
514
+
515
+ def findall(self, regexp):
516
+ """
517
+ Find instances of the regular expression in the text.
518
+ The text is a list of tokens, and a regexp pattern to match
519
+ a single token must be surrounded by angle brackets. E.g.
520
+
521
+ >>> print('hack'); from nltk.book import text1, text5, text9
522
+ hack...
523
+ >>> text5.findall("<.*><.*><bro>")
524
+ you rule bro; telling you bro; u twizted bro
525
+ >>> text1.findall("<a>(<.*>)<man>")
526
+ monied; nervous; dangerous; white; white; white; pious; queer; good;
527
+ mature; white; Cape; great; wise; wise; butterless; white; fiendish;
528
+ pale; furious; better; certain; complete; dismasted; younger; brave;
529
+ brave; brave; brave
530
+ >>> text9.findall("<th.*>{3,}")
531
+ thread through those; the thought that; that the thing; the thing
532
+ that; that that thing; through these than through; them that the;
533
+ through the thick; them that they; thought that the
534
+
535
+ :param regexp: A regular expression
536
+ :type regexp: str
537
+ """
538
+
539
+ if "_token_searcher" not in self.__dict__:
540
+ self._token_searcher = TokenSearcher(self)
541
+
542
+ hits = self._token_searcher.findall(regexp)
543
+ hits = [' '.join(h) for h in hits]
544
+ print(tokenwrap(hits, "; "))
545
+
546
+ #////////////////////////////////////////////////////////////
547
+ # Helper Methods
548
+ #////////////////////////////////////////////////////////////
549
+
550
+ _CONTEXT_RE = re.compile('\w+|[\.\!\?]')
551
+ def _context(self, tokens, i):
552
+ """
553
+ One left & one right token, both case-normalized. Skip over
554
+ non-sentence-final punctuation. Used by the ``ContextIndex``
555
+ that is created for ``similar()`` and ``common_contexts()``.
556
+ """
557
+ # Left context
558
+ j = i-1
559
+ while j>=0 and not self._CONTEXT_RE.match(tokens[j]):
560
+ j -= 1
561
+ left = (tokens[j] if j != 0 else '*START*')
562
+
563
+ # Right context
564
+ j = i+1
565
+ while j<len(tokens) and not self._CONTEXT_RE.match(tokens[j]):
566
+ j += 1
567
+ right = (tokens[j] if j != len(tokens) else '*END*')
568
+
569
+ return (left, right)
570
+
571
+ #////////////////////////////////////////////////////////////
572
+ # String Display
573
+ #////////////////////////////////////////////////////////////
574
+
575
+ def __str__(self):
576
+ return '<Text: %s>' % self.name
577
+
578
+ def __repr__(self):
579
+ return '<Text: %s>' % self.name
580
+
581
+
582
+ # Prototype only; this approach will be slow to load
583
+ class TextCollection(Text):
584
+ """A collection of texts, which can be loaded with list of texts, or
585
+ with a corpus consisting of one or more texts, and which supports
586
+ counting, concordancing, collocation discovery, etc. Initialize a
587
+ TextCollection as follows:
588
+
589
+ >>> import nltk.corpus
590
+ >>> from nltk.text import TextCollection
591
+ >>> print('hack'); from nltk.book import text1, text2, text3
592
+ hack...
593
+ >>> gutenberg = TextCollection(nltk.corpus.gutenberg)
594
+ >>> mytexts = TextCollection([text1, text2, text3])
595
+
596
+ Iterating over a TextCollection produces all the tokens of all the
597
+ texts in order.
598
+ """
599
+ def __init__(self, source):
600
+ if hasattr(source, 'words'): # bridge to the text corpus reader
601
+ source = [source.words(f) for f in source.fileids()]
602
+
603
+ self._texts = source
604
+ Text.__init__(self, LazyConcatenation(source))
605
+ self._idf_cache = {}
606
+
607
+ def tf(self, term, text):
608
+ """ The frequency of the term in text. """
609
+ return text.count(term) / len(text)
610
+
611
+ def idf(self, term):
612
+ """ The number of texts in the corpus divided by the
613
+ number of texts that the term appears in.
614
+ If a term does not appear in the corpus, 0.0 is returned. """
615
+ # idf values are cached for performance.
616
+ idf = self._idf_cache.get(term)
617
+ if idf is None:
618
+ matches = len([True for text in self._texts if term in text])
619
+ if len(self._texts) == 0:
620
+ raise ValueError('IDF undefined for empty document collection')
621
+ idf = (log(len(self._texts) / matches) if matches else 0.0)
622
+ self._idf_cache[term] = idf
623
+ return idf
624
+
625
+ def tf_idf(self, term, text):
626
+ return self.tf(term, text) * self.idf(term)
627
+
628
+ def demo():
629
+ from nltk.corpus import brown
630
+ text = Text(brown.words(categories='news'))
631
+ print(text)
632
+ print()
633
+ print("Concordance:")
634
+ text.concordance('news')
635
+ print()
636
+ print("Distributionally similar words:")
637
+ text.similar('news')
638
+ print()
639
+ print("Collocations:")
640
+ text.collocations()
641
+ print()
642
+ #print("Automatically generated text:")
643
+ #text.generate()
644
+ #print()
645
+ print("Dispersion plot:")
646
+ text.dispersion_plot(['news', 'report', 'said', 'announced'])
647
+ print()
648
+ print("Vocabulary plot:")
649
+ text.plot(50)
650
+ print()
651
+ print("Indexing:")
652
+ print("text[3]:", text[3])
653
+ print("text[3:5]:", text[3:5])
654
+ print("text.vocab()['news']:", text.vocab()['news'])
655
+
656
+ if __name__ == '__main__':
657
+ demo()
658
+
659
+ __all__ = ["ContextIndex",
660
+ "ConcordanceIndex",
661
+ "TokenSearcher",
662
+ "Text",
663
+ "TextCollection"]