{"id":22129021,"url":"https://github.com/chrispahm/spatialmerge","last_synced_at":"2025-07-19T11:35:13.296Z","repository":{"id":48172459,"uuid":"382068453","full_name":"chrispahm/spatialmerge","owner":"chrispahm","description":"A fast library for spatial joining and merging data in JavaScript 🚀","archived":false,"fork":false,"pushed_at":"2022-10-29T18:15:15.000Z","size":18476,"stargazers_count":22,"open_issues_count":1,"forks_count":3,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-06-05T10:03:40.644Z","etag":null,"topics":["browser","deno","gis","javascript","nodejs","spatial-analysis","spatial-join","spatial-joins"],"latest_commit_sha":null,"homepage":"https://observablehq.com/@chrispahm/hello-spatialmerge","language":"Jupyter Notebook","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/chrispahm.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE.md","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2021-07-01T14:56:06.000Z","updated_at":"2024-03-20T11:05:25.000Z","dependencies_parsed_at":"2023-01-20T09:35:41.012Z","dependency_job_id":null,"html_url":"https://github.com/chrispahm/spatialmerge","commit_stats":null,"previous_names":[],"tags_count":2,"template":false,"template_full_name":null,"purl":"pkg:github/chrispahm/spatialmerge","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/chrispahm%2Fspatialmerge","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/chrispahm%2Fspatialmerge/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/chrispahm%2Fspatialmerge/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/chrispahm%2Fspatialmerge/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/chrispahm","download_url":"https://codeload.github.com/chrispahm/spatialmerge/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/chrispahm%2Fspatialmerge/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":265926967,"owners_count":23850886,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["browser","deno","gis","javascript","nodejs","spatial-analysis","spatial-join","spatial-joins"],"created_at":"2024-12-01T17:57:59.795Z","updated_at":"2025-07-19T11:35:13.240Z","avatar_url":"https://github.com/chrispahm.png","language":"Jupyter Notebook","funding_links":[],"categories":[],"sub_categories":[],"readme":"# spatialmerge\n\nA (relatively) fast library for spatial joining and merging data in JavaScript.\n\n![spatialmerge](https://user-images.githubusercontent.com/20703207/124135500-25399100-da84-11eb-9c06-92db61b107e8.png)\n\nThe library is largely influenced by the [geopandas](https://geopandas.org/docs/user_guide/mergingdata.html) [merge](https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.merge.html) and [sjoin](https://geopandas.org/docs/reference/api/geopandas.sjoin.html) methods. Just as geopandas, `spatialmerge` utilizes a static spatial index provided by [Flatbush](https://github.com/mourner/flatbush) (R-tree) to narrow down the number of features to test for intersection.\n\n```js\nimport { merge, sjoin } from 'spatialmerge'\n// join the properties of a spatial dataset (GeoJSON FeatureCollection) with a\n// non-spatial dataset (e.g. contents of a CSV file parsed using d3-dsv) \n// based on a common variable\nconst resultsMerge = merge(countryShapes, countryNames, { on: 'iso_a3' })\n\n// join the properties of two spatial datasets (GeoJSON FeatureCollections)\nconst mergeSjoin = sjoin(citiesPoints, countryShapes)\n```\n\nWorking examples, and an in-depth explanation of the two functions can be found in the [user guide notebook](https://observablehq.com/@chrispahm/hello-spatialmerge).\n\n## Installing\n```shell\nnpm install spatialmerge\n# or\nyarn add spatialmerge\n```\n\nFor vanilla HTML in modern browsers, import `spatialmerge` from Skypack:\n\n```html\n\u003cscript type=\"module\"\u003e\n\nimport { merge, sjoin } from 'https://cdn.skypack.dev/spatialmerge'\n// ...\n\n\u003c/script\u003e\n```\n\nFor legacy environments, you can load `spatialmerge`’s UMD bundle from an npm-based CDN such as jsDelivr; a `spatialmerge` global is exported:\n\n```html\n\u003cscript src=\"https://cdn.jsdelivr.net/npm/spatialmerge\"\u003e\u003c/script\u003e\n```\n\n## User Guide\n\nThe User Guide is hosted as an interactive ObservableHQ notebook  \nhttps://observablehq.com/@chrispahm/hello-spatialmerge\n\n## API reference\n\n##### spatialmerge.merge(*leftFC, rightFC_or_arrayOfObjects, options = { on: \\\u003cproperty\\\u003e, mutate: false }]*)\n\nJoin the attributes of a GeoJSON FeatureCollection with an array of objects or another GeoJSON FeatureCollection based on a common variable (object key).\n\nParameters: \n- **leftFC**: *[\\\u003cGeoJSON FeatureCollection\\\u003e](https://macwright.com/2015/03/23/geojson-second-bite.html#featurecollection), required*\n- **rightFC_or_arrayOfObjects**: *[\\\u003cGeoJSON FeatureCollection\\\u003e](https://macwright.com/2015/03/23/geojson-second-bite.html#featurecollection) OR [\\\u003carray of objects\\\u003e](https://eloquentjavascript.net/04_data.html#p_d1H6/6O79A), required*\n- **options**: *\\\u003cobject\\\u003e, required*\n  - **on**: *\\\u003cstring\\\u003e, required*  \n  The key to join the two collections on.\n  - **mutate**: *\\\u003cboolean\\\u003e, default: false*  \n  Allows GeoJSON input to be mutated (significant performance increase if true) \n\n\n##### spatialmerge.sjoin(*leftFC, rightFC[, options = { how: 'inner', op: 'intersects', matches: 'all', lsuffix: 'left', rsuffix: 'right' }]*)\n\nSpatial join of two GeoJSON FeatureCollections.  \nSee the [User Guide](https://observablehq.com/@chrispahm/hello-spatialmerge) for details.\n\nParameters:\n- **leftFC, rightFC**: *[\\\u003cGeoJSON FeatureCollection\\\u003e](https://macwright.com/2015/03/23/geojson-second-bite.html#featurecollection), required*\n- **options**: *\\\u003cobject\\\u003e, optional*\n  - **how**: *\\\u003cstring\\\u003e, default: 'inner'*  \n  The type of join:\n    - ‘left’: use keys from left_df; retain only left_df geometry column\n    - ‘right’: use keys from right_df; retain only right_df geometry column\n    - ‘inner’: use intersection of keys from both dfs; retain only left_df geometry column\n  - **op**: *\\\u003cstring\\\u003e, default: 'intersects'*  \n  Binary predicate. Internally uses the corresponding [turf.js](http://turfjs.org/) modules.\n    - 'intersects'\n    - 'contains'\n    - 'within'\n    - 'crosses'\n    - 'overlaps'\n  - **matches**: *\\\u003cstring\\\u003e, default: 'all'* \n  Whether to output all results of the join operation, or only the first.\n    - 'all'\n    - 'first'\n  - **lsuffix**: *\\\u003cstring\\\u003e, default: 'left'*  \n  Suffix to apply to overlapping column names (left GeoJSON).\n  - **rsuffix**: *\\\u003cstring\\\u003e, default: 'right'*  \n  Suffix to apply to overlapping column names (right GeoJSON).\n  - **inclLeftIndex**: *\\\u003cboolean\\\u003e, default: false*  \n  Whether to include the left index as a property value in the resulting GeoJSON FeatureCollection.\n\n## Performance\n\nSpatially merging datasets is (almost) always a computationally intensive task. If you plan to use `spatialmerge` on the client side or in a Node.js / Deno server, be sure to wrap it in a [WebWorker](https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API/Using_web_workers) or [worker_thread](https://nodejs.org/api/worker_threads.html) to avoid blocking the Rendering / Event Loop. \n\nResources:\n- https://www.smashingmagazine.com/2021/06/web-workers-2021/\n- https://github.com/GoogleChromeLabs/comlink\n- https://github.com/josdejong/workerpool\n\n\n## TODOs\n\n- Fix tests for sjoin including large files, potentially using git-lfs\n- Example using WebWorker  \n- Performance comparison with @turf/tag and geopandas\n\n## Contribution\n\nContribution is highly appreciated 👍  \nPlease open an issue in case of questions / bug reports or a pull request if you implemented a new feature / bug fix.\nIn the latter case, please make sure to run npm test (and adapt test/test.js to your changes) and / or update the README 🙂\n\n## License\n\nMIT @Christoph Pahmeyer","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fchrispahm%2Fspatialmerge","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fchrispahm%2Fspatialmerge","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fchrispahm%2Fspatialmerge/lists"}