{ "info": { "author": "David Su (InfoScout)", "author_email": "david.su@infoscoutinc.com", "bugtrack_url": null, "classifiers": [ "Development Status :: 3 - Alpha", "Intended Audience :: Developers", "License :: OSI Approved :: MIT License", "Operating System :: POSIX :: Linux", "Programming Language :: Cython", "Programming Language :: Python :: 2", "Programming Language :: Python :: 2.7", "Programming Language :: Python :: 3", "Programming Language :: Python :: 3.6", "Topic :: Software Development :: Libraries :: Python Modules", "Topic :: Text Processing :: Linguistic" ], "description": "weighted-levenshtein\n====================\n\n.. image:: https://circleci.com/gh/infoscout/weighted-levenshtein.svg?style=svg\n :target: https://circleci.com/gh/infoscout/weighted-levenshtein\n\n.. image:: https://codecov.io/gh/infoscout/weighted-levenshtein/branch/master/graph/badge.svg\n :target: https://codecov.io/gh/infoscout/weighted-levenshtein\n\nUse Cases\n---------\n\nMost existing Levenshtein libraries are not very flexible: all edit operations have cost 1.\n\nHowever, sometimes not all edits are created equal. For instance, if you are doing OCR correction, maybe substituting '0' for 'O' should have a smaller cost than substituting 'X' for 'O'. If you are doing human typo correction, maybe substituting 'X' for 'Z' should have a smaller cost, since they are located next to each other on a QWERTY keyboard.\n\nThis library supports all theses use cases, by allowing the user to specify different weights for edit operations involving every possible combination of letters. The core algorithms are written in Cython, which means they are blazing fast to run.\n\nThe Levenshtein distance function supports setting different costs for inserting characters, deleting characters, and substituting characters. Thus, Levenshtein distance is well suited for detecting OCR errors.\n\nThe Damerau-Levenshtein distance function supports setting different costs for inserting characters, deleting characters, substituting characters, and transposing characters. Thus, Damerau-Levenshtein distance is well suited for detecting human typos, since humans are likely to make transposition errors, while OCR is not.\n\nMore Information\n----------------\n\nLevenshtein distance:\nhttps://en.wikipedia.org/wiki/Levenshtein\\_distance and\nhttps://en.wikipedia.org/wiki/Wagner%E2%80%93Fischer\\_algorithm\n\nOptimal String Alignment:\nhttps://en.wikipedia.org/wiki/Damerau%E2%80%93Levenshtein\\_distance#Optimal\\_string\\_alignment\\_distance\n\nDamerau-Levenshtein distance:\nhttps://en.wikipedia.org/wiki/Damerau%E2%80%93Levenshtein\\_distance#Distance\\_with\\_adjacent\\_transpositions\n\n\n\nInstallation\n------------\n\n``pip install weighted-levenshtein``\n\nUsage Example\n-------------\n\n.. code:: python\n\n import numpy as np\n from weighted_levenshtein import lev, osa, dam_lev\n\n\n insert_costs = np.ones(128, dtype=np.float64) # make an array of all 1's of size 128, the number of ASCII characters\n insert_costs[ord('D')] = 1.5 # make inserting the character 'D' have cost 1.5 (instead of 1)\n\n # you can just specify the insertion costs\n # delete_costs and substitute_costs default to 1 for all characters if unspecified\n print(lev('BANANAS', 'BANDANAS', insert_costs=insert_costs)) # prints '1.5'\n\n delete_costs = np.ones(128, dtype=np.float64)\n delete_costs[ord('S')] = 0.5 # make deleting the character 'S' have cost 0.5 (instead of 1)\n\n # or you can specify both insertion and deletion costs (though in this case insertion costs don't matter)\n print(lev('BANANAS', 'BANANA', insert_costs=insert_costs, delete_costs=delete_costs)) # prints '0.5'\n\n\n substitute_costs = np.ones((128, 128), dtype=np.float64) # make a 2D array of 1's\n substitute_costs[ord('H'), ord('B')] = 1.25 # make substituting 'H' for 'B' cost 1.25\n\n print(lev('HANANA', 'BANANA', substitute_costs=substitute_costs)) # prints '1.25'\n\n # it's not symmetrical! in this case, it is substituting 'B' for 'H'\n print(lev('BANANA', 'HANANA', substitute_costs=substitute_costs)) # prints '1'\n\n # to make it symmetrical, you need to set both costs in the 2D array\n substitute_costs[ord('B'), ord('H')] = 1.25 # make substituting 'B' for 'H' cost 1.25 as well\n\n print(lev('BANANA', 'HANANA', substitute_costs=substitute_costs)) # now it prints '1.25'\n\n\n transpose_costs = np.ones((128, 128), dtype=np.float64)\n transpose_costs[ord('A'), ord('B')] = 0.75 # make swapping 'A' for 'B' cost 0.75\n\n # note: now using dam_lev. lev does not support swapping, but osa and dam_lev do.\n # See Wikipedia links for difference between osa and dam_lev\n print(dam_lev('ABNANA', 'BANANA', transpose_costs=transpose_costs)) # prints '0.75'\n\n # like substitution, transposition is not symmetrical either!\n print(dam_lev('BANANA', 'ABNANA', transpose_costs=transpose_costs)) # prints '1'\n\n # you need to explicitly set the other direction as well\n transpose_costs[ord('B'), ord('A')] = 0.75 # make swapping 'B' for 'A' cost 0.75\n\n print(dam_lev('BANANA', 'ABNANA', transpose_costs=transpose_costs)) # now it prints '0.75'\n\n\n``lev``, ``osa``, and ``dam_lev`` are aliases for ``levenshtein``,\n``optimal_string_alignment``, and ``damerau_levenshtein``, respectively.\n\nDetailed Documentation\n----------------------\n\nhttp://weighted-levenshtein.readthedocs.io/\n\nImportant Notes\n---------------\n\n- All string lookups are case sensitive.\n\n- The costs parameters only accept numpy arrays, since the underlying Cython implementation relies on this for fast lookups. The numpy arrays are indexed using the ``ord()`` value of the characters. Thus, only the first 128 ASCII letters are accepted, and ``dict`` and ``list`` are not accepted. Consequently, the strings must be strictly ``str`` objects, not ``unicode``.\n\n- This library is compatible with both Python 2 and Python 3 (see ``tox.ini`` for tested versions).\n\n\n\nUse as Cython library\n---------------------\n\n.. code:: cython\n\n from weighted_levenshtein.clev cimport c_levenshtein as lev, c_optimal_string_alignment as osa, c_damerau_levenshtein as dam_lev\n import numpy as np\n\n a = np.ones(128, dtype=np.float64)\n b = np.ones((128, 128), dtype=np.float64)\n\n print(lev(\"BANANA\", 4, \"BANANAS\", 5, a, a, b))\n\nFor the Cython API, functions are prefixed with a ``c_`` with respect to the Python API. Also, the string parameters are followed by their length. The data types of the numpy arrays specifying the costs still need to be ``np.float64``, consistent with the Python API.\n\n\nFunction signatures below:\n\n.. code:: cython\n\n cdef double c_damerau_levenshtein(\n unsigned char* str_a,\n Py_ssize_t len_a,\n unsigned char* str_b,\n Py_ssize_t len_b,\n double[::1] insert_costs,\n double[::1] delete_costs,\n double[:,::1] substitute_costs,\n double[:,::1] transpose_costs) nogil\n\n\n cdef double c_optimal_string_alignment(\n unsigned char* word_m,\n Py_ssize_t m,\n unsigned char* word_n,\n Py_ssize_t n,\n double[::1] insert_costs,\n double[::1] delete_costs,\n double[:,::1] substitute_costs,\n double[:,::1] transpose_costs) nogil\n\n\n cdef double c_levenshtein(\n unsigned char* word_m,\n Py_ssize_t m,\n unsigned char* word_n,\n Py_ssize_t n,\n double[::1] insert_costs,\n double[::1] delete_costs,\n double[:,::1] substitute_costs) nogil", "description_content_type": "", "docs_url": null, "download_url": "", "downloads": { "last_day": -1, "last_month": -1, "last_week": -1 }, "home_page": "https://github.com/infoscout/weighted-levenshtein", "keywords": "Levenshtein Damerau weight weighted distance", "license": "MIT", "maintainer": "", "maintainer_email": "", "name": "weighted-levenshtein", "package_url": "https://pypi.org/project/weighted-levenshtein/", "platform": "", "project_url": "https://pypi.org/project/weighted-levenshtein/", "project_urls": { "Homepage": "https://github.com/infoscout/weighted-levenshtein" }, "release_url": "https://pypi.org/project/weighted-levenshtein/0.2.1/", "requires_dist": null, "requires_python": "", "summary": "Library providing functions to calculate Levenshtein distance, Optimal String Alignment distance, and Damerau-Levenshtein distance, where the cost of each operation can be weighted by letter.", "version": "0.2.1" }, "last_serial": 3870523, "releases": { "0.1": [ { "comment_text": "", "digests": { "md5": "b9005592f4d60e72122aa4e1b782e601", "sha256": "bb8a17344bce20cf9c455171f11b24e93e28ee80960b20c20a233eebb52278fb" }, "downloads": -1, "filename": "weighted_levenshtein-0.1.tar.gz", "has_sig": false, "md5_digest": "b9005592f4d60e72122aa4e1b782e601", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 104903, "upload_time": "2016-08-10T01:00:33", "url": "https://files.pythonhosted.org/packages/5b/65/494ce2d6bed3d4dc3abb9962ed2f0b86efc4ce7f2ec57a8add263fbb278e/weighted_levenshtein-0.1.tar.gz" } ], "0.2": [ { "comment_text": "", "digests": { "md5": "72cbe80954414c1ce126b6ed39c80118", "sha256": "642481a498af25cc7ea63a333ef9b04b4a5af76e9271afb0f084e73b798f67ca" }, "downloads": -1, "filename": "weighted_levenshtein-0.2.tar.gz", "has_sig": false, "md5_digest": "72cbe80954414c1ce126b6ed39c80118", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 8693, "upload_time": "2018-02-19T21:08:17", "url": "https://files.pythonhosted.org/packages/fb/82/41177f41721d9f1ddf13558d79571ab3c88ce5811585bd38de636fbce5de/weighted_levenshtein-0.2.tar.gz" } ], "0.2.1": [ { "comment_text": "", "digests": { "md5": "22464ab641737d4a5470b5b2eb241d47", "sha256": "b0d2247790944deba41d4af7f5d5e2400868a2a2de2eae8ee982c419980dd475" }, "downloads": -1, "filename": "weighted_levenshtein-0.2.1.tar.gz", "has_sig": false, "md5_digest": "22464ab641737d4a5470b5b2eb241d47", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 129457, "upload_time": "2018-05-16T23:57:13", "url": "https://files.pythonhosted.org/packages/7d/f2/17dfcf4d36abf33c8b50a664bf64685f6ba37cb477f96433a04835c7c84b/weighted_levenshtein-0.2.1.tar.gz" } ] }, "urls": [ { "comment_text": "", "digests": { "md5": "22464ab641737d4a5470b5b2eb241d47", "sha256": "b0d2247790944deba41d4af7f5d5e2400868a2a2de2eae8ee982c419980dd475" }, "downloads": -1, "filename": "weighted_levenshtein-0.2.1.tar.gz", "has_sig": false, "md5_digest": "22464ab641737d4a5470b5b2eb241d47", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 129457, "upload_time": "2018-05-16T23:57:13", "url": "https://files.pythonhosted.org/packages/7d/f2/17dfcf4d36abf33c8b50a664bf64685f6ba37cb477f96433a04835c7c84b/weighted_levenshtein-0.2.1.tar.gz" } ] }