{"id":13736087,"url":"https://github.com/r-spatial/stars","last_synced_at":"2025-05-14T02:06:16.106Z","repository":{"id":39834292,"uuid":"78360080","full_name":"r-spatial/stars","owner":"r-spatial","description":"Spatiotemporal Arrays, Raster and Vector Data Cubes","archived":false,"fork":false,"pushed_at":"2025-05-02T12:46:21.000Z","size":256702,"stargazers_count":572,"open_issues_count":38,"forks_count":96,"subscribers_count":36,"default_branch":"main","last_synced_at":"2025-05-02T13:59:03.853Z","etag":null,"topics":["r","raster","satellite-images","spatial"],"latest_commit_sha":null,"homepage":"https://r-spatial.github.io/stars/","language":"R","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/r-spatial.png","metadata":{"files":{"readme":"README.Rmd","changelog":"NEWS.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2017-01-08T17:48:24.000Z","updated_at":"2025-05-02T12:41:14.000Z","dependencies_parsed_at":"2024-02-23T10:28:37.941Z","dependency_job_id":"80d1f7fb-3ace-42c3-b364-5fae9ce6b03d","html_url":"https://github.com/r-spatial/stars","commit_stats":{"total_commits":1889,"total_committers":44,"mean_commits":42.93181818181818,"dds":"0.15140285865537317","last_synced_commit":"809f9f57267d65329f8ef80d9ddec7430f2fb4db"},"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/r-spatial%2Fstars","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/r-spatial%2Fstars/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/r-spatial%2Fstars/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/r-spatial%2Fstars/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/r-spatial","download_url":"https://codeload.github.com/r-spatial/stars/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":254052696,"owners_count":22006716,"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":["r","raster","satellite-images","spatial"],"created_at":"2024-08-03T03:01:15.520Z","updated_at":"2025-05-14T02:06:11.093Z","avatar_url":"https://github.com/r-spatial.png","language":"R","readme":"---\noutput: github_document\n---\n\n```{r setup, echo = FALSE}\nknitr::opts_chunk$set(\n  collapse = TRUE,\n  comment = \"#\",\n  fig.path = \"man/figures/README-\"\n)\nis_online = curl::has_internet()\n```\n\n# Spatiotemporal Arrays: Raster and Vector Datacubes\n\n\u003c!-- badges: start --\u003e\n[![R-CMD-check](https://github.com/r-spatial/stars/actions/workflows/R-CMD-check.yaml/badge.svg)](https://github.com/r-spatial/stars/actions/workflows/R-CMD-check.yaml)\n[![CRAN](https://www.r-pkg.org/badges/version/stars)](https://cran.r-project.org/package=stars) \n[![cran checks](https://badges.cranchecks.info/worst/stars.svg)](https://cran.r-project.org/web/checks/check_results_stars.html)\n[![Downloads](https://cranlogs.r-pkg.org/badges/stars?color=brightgreen)](https://www.r-pkg.org/pkg/stars)\n[![status](https://tinyverse.netlify.app/badge/stars)](https://CRAN.R-project.org/package=stars)\n[![Codecov test coverage](https://codecov.io/gh/r-spatial/stars/branch/main/graph/badge.svg)](https://app.codecov.io/gh/r-spatial/stars?branch=main)\n\u003c!-- badges: end --\u003e\n\n\nSpatiotemporal data often comes in the form of dense arrays, with space and time being array dimensions. Examples include\n\n-   socio-economic or demographic data,\n-   environmental variables monitored at fixed stations,\n-   raster maps,\n-   time series of satellite images with multiple spectral bands,\n-   spatial simulations, and\n-   climate or weather model output.\n\nThis R package provides classes and methods for reading,\nmanipulating, plotting and writing such data cubes, to the extent\nthat there are proper formats for doing so.\n\n## Raster and vector data cubes\n\nThe canonical data cube most of us have in mind is that where two\ndimensions represent spatial raster dimensions, and the third time\n(or band), as e.g. shown here:\n\n```{r cube1,out.width='50%',echo=FALSE}\nknitr::include_graphics(\"https://raw.githubusercontent.com/r-spatial/stars/main/images/cube1.png\")\n```\n\nBy data cubes however we also consider higher-dimensional cubes\n(hypercubes) such as a five-dimensional cube where in addition to\ntime, spectral band and sensor form dimensions:\n\n```{r cube2,out.width='50%',echo=FALSE}\nknitr::include_graphics(\"https://raw.githubusercontent.com/r-spatial/stars/main/images/cube2.png\")\n```\n\nor lower-dimensional cubes such as a raster image:\n```{r plot1, message=FALSE}\nlibrary(dplyr)\nlibrary(stars)\ntif = system.file(\"tif/L7_ETMs.tif\", package = \"stars\")\nread_stars(tif) |\u003e\n  slice(index = 1, along = \"band\") |\u003e\n  plot()\n```\n\nRaster data do not need to be regular and aligned with North/East,\nand package `stars` supports besides _regular_ also _rotated_,\n_sheared_, _rectilinear_ and _curvilinear_ rasters:\n\n```{r plot2,echo=FALSE}\nx = 1:5\ny = 1:4\nd = st_dimensions(x = x, y = y, .raster = c(\"x\", \"y\"))\nm = matrix(runif(20),5,4)\nr1 = st_as_stars(r = m, dimensions = d)\n\nr = attr(d, \"raster\")\nr$affine = c(0.2, -0.2)\nattr(d, \"raster\") = r\nr2 = st_as_stars(r = m, dimensions = d)\n\nr = attr(d, \"raster\")\nr$affine = c(0.1, -0.3)\nattr(d, \"raster\") = r\nr3 = st_as_stars(r = m, dimensions = d)\n\nx = c(1, 2, 3.5, 5, 6)\ny = c(1, 1.5, 3, 3.5)\nd = st_dimensions(x = x, y = y, .raster = c(\"x\", \"y\"))\nr4 = st_as_stars(r = m, dimensions = d)\n\ngrd = st_make_grid(cellsize = c(10,10), offset = c(-130,10), n = c(8,5), crs = st_crs(4326))\nr5 = st_transform(grd, \"+proj=laea +lon_0=-70 +lat_0=35\")\n\npar(mfrow = c(2,3))\nr1 = st_make_grid(cellsize = c(1,1), n = c(5,4), offset = c(0,0))\nplot(r1, main = \"regular\")\nplot(st_geometry(st_as_sf(r2)), main = \"rotated\")\nplot(st_geometry(st_as_sf(r3)), main = \"sheared\")\nplot(st_geometry(st_as_sf(r4, as_points = FALSE)), main = \"rectilinear\")\nplot(st_geometry((r5)), main = \"curvilinear\")\n```\n\nVector data cubes arise when we do not have two regularly discretized spatial dimensions, but a single dimension that points to distinct spatial feature geometries, such as polygons (e.g. denoting administrative regions):\n\n```{r cube3,out.width='50%',echo=FALSE}\nknitr::include_graphics(\"https://raw.githubusercontent.com/r-spatial/stars/main/images/cube3.png\")\n```\n\nor points (e.g. denoting sensor locations):\n\n```{r cube4,out.width='50%',echo=FALSE}\nknitr::include_graphics(\"https://raw.githubusercontent.com/r-spatial/stars/main/images/cube4.png\")\n```\n\nNetCDF's CF-convention calls this a [discrete axis](https://cfconventions.org/Data/cf-conventions/cf-conventions-1.8/cf-conventions.html#discrete-axis).\n\n## NetCDF, GDAL\n\n`stars` provides two functions to read data: `read_ncdf` and\n`read_stars`, where the latter reads through GDAL. (In the future,\nboth will be integrated in `read_stars`.) For reading NetCDF files,\npackage `RNetCDF` is used, for reading through GDAL, package `sf`\nprovides the binary linking to GDAL.\n\nFor vector and raster operations, `stars` uses as much as possible\nthe routines available in GDAL and PROJ (e.g. `st_transform`,\n`rasterize`, `polygonize`, `warp`). Read more about this in\nthe vignette on [vector-raster conversions, reprojection,\nwarping](https://r-spatial.github.io/stars/articles/stars5.html).\n\n## Out-of-memory (on-disk) rasters\n\nPackage `stars` provides `stars_proxy` objects (currently only when\nread through GDAL), which contain only the dimensions metadata and\npointers to the files on disk. These objects work lazily: reading\nand processing data is postponed to the moment that pixels are\nreally needed (at plot time, or when writing to disk), and is done\nat the lowest spatial resolution possible that still fulfills the\nresolution of the graphics device. More\ndetails are found in the [stars proxy\nvignette](https://r-spatial.github.io/stars/articles/stars2.html).\n\nThe following methods are currently available for `stars_proxy` objects:\n```{r methods}\nmethods(class = \"stars_proxy\")\n```\n\n## Raster and vector time series analysis example\n\nIn the following, a curvilinear grid with hourly precipitation values of\na hurricane is imported and the first 12 time steps are plotted:\n\n```{r plot3}\nprec_file = system.file(\"nc/test_stageiv_xyt.nc\", package = \"stars\")\n(prec = read_stars(gdal_subdatasets(prec_file)[[1]]))\n# or: (prec = read_ncdf(prec_file, curvilinear = c(\"lon\", \"lat\"), ignore_bounds = TRUE))\nsf::read_sf(system.file(\"gpkg/nc.gpkg\", package = \"sf\"), \"nc.gpkg\") |\u003e \n  st_transform(st_crs(prec)) -\u003e nc # transform from NAD27 to WGS84\nnc_outline = st_union(st_geometry(nc))\nplot_hook = function() plot(nc_outline, border = 'red', add = TRUE)\nprec |\u003e\n  slice(index = 1:12, along = \"time\") |\u003e\n  plot(downsample = c(3, 3, 1), hook = plot_hook)\n```\n\nand next, intersected with with the counties of North Carolina, where\nthe maximum precipitation intensity was obtained per county, and plotted:\n\n```{r plot4}\na = aggregate(prec, by = nc, FUN = max)\nplot(a, max.plot = 23, border = 'grey', lwd = .5)\n```\n\nWe can integrate over (reduce) time, for instance to find out _when_\nthe maximum precipitation occurred. The following code finds the time\nindex, and then the corresponding time value:\n\n```{r plot5, fig.height=3}\nindex_max = function(x) ifelse(all(is.na(x)), NA, which.max(x))\nb = st_apply(a, \"geom\", index_max)\nb |\u003e mutate(when = st_get_dimension_values(a, \"time\")[b$index_max]) |\u003e\n  select(when) |\u003e\n  plot(key.pos = 1, main = \"time of maximum precipitation\")\n```\n\nWith package `cubble`, we can make a glyph map to see the magnitude and timings of county maximum precipitation:\n```{r plot6, fig.height=3, message=FALSE, warning=FALSE}\nlibrary(cubble)\nlibrary(ggplot2)\na |\u003e setNames(\"precip\") |\u003e\n  st_set_dimensions(2, name = \"tm\") |\u003e\n  units::drop_units() |\u003e\n  as_cubble(key = id, index = tm) -\u003e a.cb\na.cb |\u003e\n  face_temporal() |\u003e\n  unfold(long, lat) |\u003e\n  mutate(tm = as.numeric(tm)) |\u003e\n  ggplot(aes(x_major = long, x_minor = tm, y_major = lat, y_minor = precip)) +\n  geom_sf(data = nc, inherit.aes = FALSE) +\n  geom_glyph_box(width = 0.3, height = 0.1) +\n  geom_glyph(width = 0.3, height = 0.1)\n```\n\n## Other packages for data cubes\n\n### [`gdalcubes`](https://github.com/appelmar/gdalcubes)\n\nPackage `gdalcubes` can be used to create data cubes (or functions\nfrom them) from image collections, sets of multi-band images with\nvarying\n\n* spatial resolution\n* spatial extent\n* coordinate reference systems (e.g., spread over multiple UTM zones)\n* observation times\n\nand does this by resampling and/or aggregating over space and/or\ntime. It reuses GDAL VRT's and gdalwarp for spatial resampling and/or\nwarping, and handles temporal resampling or aggregation itself.\n\n### [`ncdfgeom`](https://github.com/DOI-USGS/ncdfgeom)\n\n`ncdfgeom` reads and writes vector data cubes from and to netcdf\nfiles in a standards-compliant way.\n\n### [`raster`](https://github.com/rspatial/raster/) and [`terra`](https://github.com/rspatial/terra/)\n\nPackages `raster` and its successor, `terra` are powerful packages\nfor handling raster maps and stacks of raster maps both in memory\nand on disk, but do not address\n\n* non-raster time series, \n* multi-attribute rasters time series\n* rasters with mixed type attributes (e.g., numeric, logical, factor, POSIXct)\n* rectilinear or curvilinear rasters\n\nA list of `stars` commands matching\nexisting `raster` commands is found in this\n[wiki](https://github.com/r-spatial/stars/wiki/How-%60raster%60-functions-map-to-%60stars%60-functions).\nA list of translations in the opposite direction (from `stars` to\n`raster` or `terra`) still needs to be made. \n\nA comment on the differences between `stars` and `terra` is found\n[here](https://github.com/r-spatial/stars/issues/633).\n\n## Other `stars` resources:\n\n* blog posts: [first](https://r-spatial.org/r/2017/11/23/stars1.html),\n[second](https://r-spatial.org/r/2018/03/22/stars2.html),\n[third](https://r-spatial.org/r/2018/03/23/stars3.html), and [newer blog posts](https://r-spatial.org/)\n* [vignettes](https://r-spatial.github.io/stars/articles/)\n* the original [R Consortium proposal](https://github.com/r-spatial/stars/blob/main/PROPOSAL.md).\n\n### Acknowledgment\n\nThis project has been realized with financial\n[support](https://www.r-consortium.org/blog/2017/04/03/q1-2017-isc-grants)\nfrom the\n\n\u003ca href=\"https://r-consortium.org/all-projects/2017-group-1.html#stars-scalable-spatiotemporal-tidy-arrays-for-r\"\u003e\n\u003cimg src=\"https://r-consortium.org/images/RConsortium_Horizontal_Pantone.webp\" width=\"300\"\u003e\n\u003c/a\u003e\n\u003c!--\n\u003cimg src=\"http://pebesma.staff.ifgi.de/RConsortium_Horizontal_Pantone.png\" width=\"300\"\u003e\n--\u003e\n","funding_links":[],"categories":["Resources for `R`","R","Geospatial Library"],"sub_categories":["Testing your code","R"],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fr-spatial%2Fstars","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fr-spatial%2Fstars","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fr-spatial%2Fstars/lists"}