{ "info": { "author": "Justin Shenk", "author_email": "shenkjustin@gmail.com", "bugtrack_url": null, "classifiers": [ "Intended Audience :: Developers", "Intended Audience :: Education", "Intended Audience :: Science/Research", "License :: OSI Approved :: MIT License", "Programming Language :: Python :: 3", "Programming Language :: Python :: 3.6", "Topic :: Scientific/Engineering :: Mathematics", "Topic :: Software Development :: Libraries", "Topic :: Software Development :: Libraries :: Python Modules" ], "description": "# Closely :triangular_ruler:\n [![PyPI version](https://badge.fury.io/py/closely.svg)](https://badge.fury.io/py/closely) [![Build Status](https://travis-ci.com/justinshenk/closely.svg?branch=master)](https://travis-ci.com/justinshenk/closely)\n\n\nFind the closest pairs in an array. \n\nClosely uses principal component analysis (PCA) to reduce the dimensions to 2 and a divide and conquer algorithm to find the closest pair of points.\n\n### Getting Started\n\n```bash\npip install closely\n```\n\nor install from source:\n```bash\ngit clone https://github.com/justinshenk/closely\ncd closely\npip install .\n```\n\n### How to use\n\n```python\nimport closely\n\n# X is an n x m numpy array\npairs, distances = closely.solve(X, n=1)\n```\n\nYou can specify how many pairs you want to identify with `n`.\n\n\n### Example\n```python\nimport closely\nimport numpy as np\nimport matplotlib.pyplot as plt\n\n# Create dataset\nX = np.random.random((100,2))\npairs, distance = closely.solve(X, n=1)\n\n# Plot points\nz, y = np.split(X, 2, axis=1)\nfig, ax = plt.subplots()\nax.scatter(z, y) \n\nfor i, txt in enumerate(X): \n if i in pairs: \n ax.annotate(i, (z[i], y[i]), color='red') \n else: \n ax.annotate(i, (z[i], y[i]))\n\nplt.show() \n```\n\nCheck pairs:\n```ipython\nIn [10]: pairs \nOut[10]: \narray([[ 7, 16],\n [96, 50]])\n\n```\n\nOutput:\n![example_plot](example_plot.png)\n\n\n### Caveats\nIf your data has more than 3 features, `closely` will reduce the dimensionality by projecting it onto two directions that explain most of the variance. This speeds up processing, but is not 100% precise. In other words, if your data has four columns (eg, x, y, z, a), it will apply divide-and-conquer on the new projection bases P1 and P2.\n\nIt also removes the first point in a pair if `n`>1. In rare cases this leads to false negatives if the data is highly overlapping.\n\n\n### Credit and Explanation\n\nPython code modified from [Andriy Lazorenko](https://medium.com/@andriylazorenko/closest-pair-of-points-in-python-79e2409fc0b2), packaged and made useful for >2 features by Justin Shenk.\n\n\n", "description_content_type": "text/markdown", "docs_url": null, "download_url": "", "downloads": { "last_day": -1, "last_month": -1, "last_week": -1 }, "home_page": "https://github.com/justinshenk/closely", "keywords": "mathematics,geometry,closest pairs,similar data,duplicates", "license": "MIT", "maintainer": "Justin Shenk", "maintainer_email": "shenkjustin@gmail.com", "name": "closely", "package_url": "https://pypi.org/project/closely/", "platform": "", "project_url": "https://pypi.org/project/closely/", "project_urls": { "Homepage": "https://github.com/justinshenk/closely" }, "release_url": "https://pypi.org/project/closely/19.0.2/", "requires_dist": [ "numpy", "scipy", "matplotlib ; extra == 'all'", "fastcluster ; extra == 'all'", "coverage ; extra == 'dev'", "pytest ; extra == 'dev'", "matplotlib ; extra == 'dev'", "fastcluster ; extra == 'dev'", "sphinx ; extra == 'dev'", "wheel ; extra == 'dev'", "pre-commit ; extra == 'dev'", "sphinx ; extra == 'docs'", "coverage ; extra == 'tests'", "pytest ; extra == 'tests'" ], "requires_python": ">= 3.6", "summary": "Closely find closest pairs of points, eg duplicates, in a dataset", "version": "19.0.2" }, "last_serial": 5378289, "releases": { "0.1.5": [ { "comment_text": "", "digests": { "md5": "ce242b860d0f761afe5c55ec3346563f", "sha256": "ba55a01b166b024dbd16ebec6e2447ab8f9ad726e3ce1e1de04d28687821b4e6" }, "downloads": -1, "filename": "closely-0.1.5-py3-none-any.whl", "has_sig": false, "md5_digest": "ce242b860d0f761afe5c55ec3346563f", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": ">= 3.6", "size": 4707, "upload_time": "2019-05-22T16:06:27", "url": "https://files.pythonhosted.org/packages/ee/15/42d1141b345da4ee527e9a69e638f0e406f3c982e45157f214b5994fbdf2/closely-0.1.5-py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "5af4dd3c06ad82106dab8d2cc335370a", "sha256": "39b8af5bee870e1ada2cc90516aeca4bad97027aa846ddd82b4b03cd3a6769a5" }, "downloads": -1, "filename": "closely-0.1.5.tar.gz", "has_sig": false, "md5_digest": "5af4dd3c06ad82106dab8d2cc335370a", "packagetype": "sdist", "python_version": "source", "requires_python": ">= 3.6", "size": 4046, "upload_time": "2019-05-22T16:06:29", "url": "https://files.pythonhosted.org/packages/95/58/efefaf3100a1f7aaa0c493a9264ed478e5b755860e915f7b133a65c4be10/closely-0.1.5.tar.gz" } ], "0.1.6": [ { "comment_text": "", "digests": { "md5": "caf3416cb34591ad40e03663c9353be9", "sha256": "b14f7cf826cfe7de7deaff3a78749253d5f0b8165a673e683e2ba36f3be122f8" }, "downloads": -1, "filename": "closely-0.1.6-py3-none-any.whl", "has_sig": false, "md5_digest": "caf3416cb34591ad40e03663c9353be9", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": ">= 3.6", "size": 5313, "upload_time": "2019-05-23T20:39:27", "url": "https://files.pythonhosted.org/packages/e8/1c/7cab0cc46564f985e2cf4123ec68ad806fce846bf754370d708d0cb3d73c/closely-0.1.6-py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "4ef48c8c2b367ed7bd3c698a1a4e1095", "sha256": "c33834d8fc71d05a7e7fcf5f7ec30a8dfd169d1dcc123d46b70e916996012091" }, "downloads": -1, "filename": "closely-0.1.6.tar.gz", "has_sig": false, "md5_digest": "4ef48c8c2b367ed7bd3c698a1a4e1095", "packagetype": "sdist", "python_version": "source", "requires_python": ">= 3.6", "size": 4294, "upload_time": "2019-05-23T20:39:29", "url": "https://files.pythonhosted.org/packages/f4/b0/8811057a460c86618c21aa9b9ccbfd03abc027bd37782630c0d0e8182a50/closely-0.1.6.tar.gz" } ], "0.1.8": [ { "comment_text": "", "digests": { "md5": "91633105b128a4e225d6e65924062a3e", "sha256": "eb6f0f5776eafe27f103d6ee71bd5ecda34368bb206f58d720512448403b96db" }, "downloads": -1, "filename": "closely-0.1.8.tar.gz", "has_sig": false, "md5_digest": "91633105b128a4e225d6e65924062a3e", "packagetype": "sdist", "python_version": "source", "requires_python": ">= 3.6", "size": 3430, "upload_time": "2019-05-25T21:04:57", "url": "https://files.pythonhosted.org/packages/24/92/bde13df7168d114a776a1539f55a9149f8007bf99007f570870c86d2df78/closely-0.1.8.tar.gz" } ], "19.0.0": [ { "comment_text": "", "digests": { "md5": "2011ffc951e0755996499d7820286e0a", "sha256": "07aabc5b91aad528eca03d0c0316b0cc499c9b2371163bb09a90cd256df387fe" }, "downloads": -1, "filename": "closely-19.0.0-py3-none-any.whl", "has_sig": false, "md5_digest": "2011ffc951e0755996499d7820286e0a", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": ">= 3.6", "size": 4743, "upload_time": "2019-05-26T16:23:05", "url": "https://files.pythonhosted.org/packages/0e/3e/273801e68e036b828dcbddc7ef4fb22bc09a1832c487731b660f99e4debd/closely-19.0.0-py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "92f8de726ceee785b4580bc79a3516ee", "sha256": "3ad32f8889f027c2ff85e5c6f3f61910cdcf8346c09e33e1302957e4739652b3" }, "downloads": -1, "filename": "closely-19.0.0.tar.gz", "has_sig": false, "md5_digest": "92f8de726ceee785b4580bc79a3516ee", "packagetype": "sdist", "python_version": "source", "requires_python": ">= 3.6", "size": 5461, "upload_time": "2019-05-26T16:23:07", "url": "https://files.pythonhosted.org/packages/6d/2a/d48e7db014fac9c747640fb8eb80446c25da52b4a85c214e4229479d4766/closely-19.0.0.tar.gz" } ], "19.0.1": [ { "comment_text": "", "digests": { "md5": "be64d0efa07deaa1595e1b24a9329a6d", "sha256": "964ecdc596ea336184b4cb1bf0281d1523cd27852bf2d84427e53adfbea6828c" }, "downloads": -1, "filename": "closely-19.0.1-py3-none-any.whl", "has_sig": false, "md5_digest": "be64d0efa07deaa1595e1b24a9329a6d", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": ">= 3.6", "size": 5955, "upload_time": "2019-05-27T21:42:25", "url": "https://files.pythonhosted.org/packages/b4/f6/99fc6944267cd8adfbffdb98555d17f5ed913a82464ac6f7ccdf0e8cad93/closely-19.0.1-py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "ed2efa478c94f137b6ba4433442e9ff9", "sha256": "d82c806ef0fbb577c4fdbd01c83e8b910e949c6cdfaa9c43a4d34b8d01973c12" }, "downloads": -1, "filename": "closely-19.0.1.tar.gz", "has_sig": false, "md5_digest": "ed2efa478c94f137b6ba4433442e9ff9", "packagetype": "sdist", "python_version": "source", "requires_python": ">= 3.6", "size": 6683, "upload_time": "2019-05-27T21:42:26", "url": "https://files.pythonhosted.org/packages/66/1c/07179495d3ff0762b33c69b2029b8720207f7c9b74c6eaa0ef4b4a250f66/closely-19.0.1.tar.gz" } ], "19.0.2": [ { "comment_text": "", "digests": { "md5": "d4e32a05bfd2f5b4741bd2e2772e1ac0", "sha256": "739365668d6beeed40137d28b937abeaa1ca2e6dd15d71eced9750c819b73125" }, "downloads": -1, "filename": "closely-19.0.2-py3-none-any.whl", "has_sig": false, "md5_digest": "d4e32a05bfd2f5b4741bd2e2772e1ac0", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": ">= 3.6", "size": 6059, "upload_time": "2019-05-29T17:10:52", "url": "https://files.pythonhosted.org/packages/39/c1/126873342cd0ea249321adbaf3766a771a986d1b09d935a578116e890aaa/closely-19.0.2-py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "3ce3ef61a954b1cd02ba69fa8cf04c4a", "sha256": "848ab89b9d6958c938ca83225c26cae476fb5ebba86f054eaedb77513498dff4" }, "downloads": -1, "filename": "closely-19.0.2.tar.gz", "has_sig": false, "md5_digest": "3ce3ef61a954b1cd02ba69fa8cf04c4a", "packagetype": "sdist", "python_version": "source", "requires_python": ">= 3.6", "size": 6833, "upload_time": "2019-05-29T17:10:53", "url": "https://files.pythonhosted.org/packages/8e/46/82d1d9d0b2a42af880c7dda3f57d1b065681d9f1b2c51c7519347cb776ae/closely-19.0.2.tar.gz" } ], "19.0.2.dev0": [ { "comment_text": "", "digests": { "md5": "06dba047d161b91743ebf976cb1750b2", "sha256": "75c67c61a72f5a956fa5cd336b78b099fbf639eeeca9c6b4acb50fa9967113e1" }, "downloads": -1, "filename": "closely-19.0.2.dev0.tar.gz", "has_sig": false, "md5_digest": "06dba047d161b91743ebf976cb1750b2", "packagetype": "sdist", "python_version": "source", "requires_python": ">= 3.6", "size": 6502, "upload_time": "2019-06-09T17:59:51", "url": "https://files.pythonhosted.org/packages/de/b8/9eca3a2b22ba1d0d226cd8a9edf4ed8e59b7134adf7325c766af5d03f559/closely-19.0.2.dev0.tar.gz" } ] }, "urls": [ { "comment_text": "", "digests": { "md5": "d4e32a05bfd2f5b4741bd2e2772e1ac0", "sha256": "739365668d6beeed40137d28b937abeaa1ca2e6dd15d71eced9750c819b73125" }, "downloads": -1, "filename": "closely-19.0.2-py3-none-any.whl", "has_sig": false, "md5_digest": "d4e32a05bfd2f5b4741bd2e2772e1ac0", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": ">= 3.6", "size": 6059, "upload_time": "2019-05-29T17:10:52", "url": "https://files.pythonhosted.org/packages/39/c1/126873342cd0ea249321adbaf3766a771a986d1b09d935a578116e890aaa/closely-19.0.2-py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "3ce3ef61a954b1cd02ba69fa8cf04c4a", "sha256": "848ab89b9d6958c938ca83225c26cae476fb5ebba86f054eaedb77513498dff4" }, "downloads": -1, "filename": "closely-19.0.2.tar.gz", "has_sig": false, "md5_digest": "3ce3ef61a954b1cd02ba69fa8cf04c4a", "packagetype": "sdist", "python_version": "source", "requires_python": ">= 3.6", "size": 6833, "upload_time": "2019-05-29T17:10:53", "url": "https://files.pythonhosted.org/packages/8e/46/82d1d9d0b2a42af880c7dda3f57d1b065681d9f1b2c51c7519347cb776ae/closely-19.0.2.tar.gz" } ] }