Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature request: add function "table" to aggregate() #1662

Open
AramburuMerlos opened this issue Dec 5, 2024 · 3 comments
Open

Feature request: add function "table" to aggregate() #1662

AramburuMerlos opened this issue Dec 5, 2024 · 3 comments

Comments

@AramburuMerlos
Copy link
Contributor

aggregate() only works with functions that return a single number (e.g., sum, mean, modal, min, max). It would be very handy if there is also an option to get the frequency of each value in the aggregated cell (as with function "table"), particularly for rasters with "classes type" values.

To achieve that, I am currently doing the following (which is not very efficient). Maybe there already is a better way to do it?

library(terra)

r <- rast(nrow = 100, ncol = 100)
values(r) <- sample(1:8, 1e4, replace = T)

# it would be great if this works:
# ra <- aggregate(r, fact=4, fun = "table", na.rm = TRUE)

# right now I am doing:
ra <- vector(mode = "list", length = 8)

ra[[1]] <- aggregate(r, fact=4, fun = function(x) sum(x == 1, na.rm = TRUE))
ra[[2]] <- aggregate(r, fact=4, fun = function(x) sum(x == 2, na.rm = TRUE))
ra[[3]] <- aggregate(r, fact=4, fun = function(x) sum(x == 3, na.rm = TRUE))
ra[[4]] <- aggregate(r, fact=4, fun = function(x) sum(x == 4, na.rm = TRUE))
ra[[5]] <- aggregate(r, fact=4, fun = function(x) sum(x == 5, na.rm = TRUE))
ra[[6]] <- aggregate(r, fact=4, fun = function(x) sum(x == 6, na.rm = TRUE))
ra[[7]] <- aggregate(r, fact=4, fun = function(x) sum(x == 7, na.rm = TRUE))
ra[[8]] <- aggregate(r, fact=4, fun = function(x) sum(x == 8, na.rm = TRUE))

ra <- do.call(c, ra)


@rhijmans
Copy link
Member

rhijmans commented Dec 7, 2024

I agree that this could be build in; although it is a tricky one. Right now, you can do

library(terra)
r <- rast(nrow = 100, ncol = 100)
values(r) <- sample(1:8, 1e4, replace = T)
r[50, ] <- NA

tabfun <- function(x, n=8, na.rm=FALSE) {
	if (na.rm) {
		if (all(is.na(x))) {
			return(rep(NA, n))
		}
	} else if (any(is.na(x))) {
		return(rep(NA, n))
	}
	table(factor(x, levels=1:n))
}

ra <- aggregate(r, fact=4, fun = tabfun)
rb <- aggregate(r, fact=4, fun = tabfun, na.rm=TRUE)

@AramburuMerlos
Copy link
Contributor Author

Thanks!
I didn't realize that you can use a function that returns multiple values in aggregate. The function documentation states the opposite.
I notice that aggregate(r, fun = function(x) range(x)) also works but not aggregate(r, fun = function(x) unique(x)).
So, it works as long as it returns the same number of values, right?
Should this be clarified in the aggregate help file?

rhijmans added a commit that referenced this issue Dec 18, 2024
@rhijmans
Copy link
Member

Thanks, I improved the manual and plan to "build-in" the "table" function soon.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants