Skip to content

Commit

Permalink
fixes #1335
Browse files Browse the repository at this point in the history
  • Loading branch information
rhijmans committed Nov 11, 2023
1 parent bf17ae4 commit 473b782
Show file tree
Hide file tree
Showing 3 changed files with 45 additions and 26 deletions.
24 changes: 17 additions & 7 deletions R/extract.R
Original file line number Diff line number Diff line change
Expand Up @@ -224,15 +224,21 @@ extract_table <- function(x, y, ID=FALSE, weights=FALSE, exact=FALSE, touches=FA

extract_fun <- function(x, y, fun, ID=TRUE, weights=FALSE, exact=FALSE, touches=FALSE, layer=NULL, bind=FALSE, na.rm=FALSE) {

opt <- spatOptions()
nl <- nlyr(x)
nf <- length(fun)
if ((nf > 1) & (!is.null(layer))) {
error("extract", "you cannot use argument 'layer' when using multiple functions")
}

opt <- spatOptions()
e <- x@cpp$extractVectorFlat(y@cpp, fun, na.rm, touches[1], "", FALSE, FALSE, weights, exact, opt)
x <- messages(x, "extract")

nl <- nlyr(x)
e <- data.frame(matrix(e, ncol=nl, byrow=TRUE))
colnames(e) <- names(x)

e <- data.frame(matrix(e, ncol=nl*nf, byrow=TRUE))
if (nf == 1) {
colnames(e) <- names(x)
} else {
colnames(e) <- apply(cbind(rep(fun, each=nl), names(x)), 1, function(i) paste(i, collapse="_"))
}
if (!is.null(layer)) {
e <- cbind(ID=1:nrow(e), e)
e <- use_layer(e, y, layer, nlyr(x))
Expand All @@ -245,6 +251,7 @@ extract_fun <- function(x, y, fun, ID=TRUE, weights=FALSE, exact=FALSE, touches=
if (nrow(e) == nrow(y)) {
e <- cbind(y, e)
} else {
#? can this occur?
warn("extract", "cannot return a SpatVector because the number of records extracted does not match he number of rows in y (perhaps you need to use a summarizing function")
}
} else if (ID) {
Expand Down Expand Up @@ -288,7 +295,10 @@ function(x, y, fun=NULL, method="simple", cells=FALSE, xy=FALSE, ID=TRUE, weight
} else if (!is.null(fun)) { # nothing to summarize for points
txtfun <- .makeTextFun(fun)
if (inherits(txtfun, "character")) {
if (txtfun == "table") {
if (any(txtfun == "table")) {
if (length(fun) > 1) {
warn("extract", "'table' cannot be combined with other functions")
}
if (!is.null(layer)) {
warn("extract", "argument 'layer' is ignored when 'fun=table'")
}
Expand Down
45 changes: 27 additions & 18 deletions src/extract.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -898,7 +898,7 @@ std::vector<double> SpatRaster::extractVectorFlat(SpatVector v, std::string fun,
*/


std::vector<double> SpatRaster::extractVectorFlat(SpatVector v, std::string fun, bool narm, bool touches, std::string method, bool cells, bool xy, bool weights, bool exact, SpatOptions &opt) {
std::vector<double> SpatRaster::extractVectorFlat(SpatVector v, std::vector<std::string> funs, bool narm, bool touches, std::string method, bool cells, bool xy, bool weights, bool exact, SpatOptions &opt) {

if (!source[0].srs.is_same(v.srs, true)) {
v = v.project(getSRS("wkt"), false);
Expand Down Expand Up @@ -983,19 +983,25 @@ std::vector<double> SpatRaster::extractVectorFlat(SpatVector v, std::string fun,

SpatRaster r = geometry(1);
//std::vector<double> feats(1, 1) ;
std::function<double(std::vector<double>&, size_t, size_t)> efun;
std::function<double(std::vector<double>&, std::vector<double>&, size_t, size_t)> wfun;
std::vector<std::function<double(std::vector<double>&, size_t, size_t)>> efuns;
std::vector<std::function<double(std::vector<double>&, std::vector<double>&, size_t, size_t)>> wfuns;
bool havefun = false;
if (!fun.empty()) {
if (!funs.empty()) {
if (weights | exact) {
if (!getseWfun(wfun, fun, narm)) {
setError("not a valid function");
return flat;
wfuns.resize(funs.size());
for (size_t i=0; i<funs.size(); i++) {
if (!getseWfun(wfuns[i], funs[i], narm)) {
setError(funs[i] + " is not a valid function");
return flat;
}
}
} else {
if (!getseFun(efun, fun, narm)) {
setError("not a valid function");
return flat;
efuns.resize(funs.size());
for (size_t i=0; i<funs.size(); i++) {
if (!getseFun(efuns[i], funs[i], narm)) {
setError(funs[i] + " is not a valid function");
return flat;
}
}
}
havefun = true;
Expand Down Expand Up @@ -1027,15 +1033,18 @@ std::vector<double> SpatRaster::extractVectorFlat(SpatVector v, std::string fun,
if (havefun) {
std::vector<std::vector<double>> cvals = extractCell(cell);
if (weights | exact) {
for (size_t j=0; j<nl; j++) {
flat.push_back( wfun(cvals[j], wgt, 0, cvals[j].size()) );
}
for (size_t j=0; j<funs.size(); j++) {
for (size_t k=0; k<nl; k++) {
flat.push_back( wfuns[j](cvals[k], wgt, 0, cvals[k].size()) );
}
}
} else {
for (size_t j=0; j<nl; j++) {
flat.push_back( efun(cvals[j], 0, cvals[j].size()) );
}
}

for (size_t j=0; j<funs.size(); j++) {
for (size_t k=0; k<nl; k++) {
flat.push_back( efuns[j](cvals[k], 0, cvals[k].size()) );
}
}
}
} else {
out[i] = extractCell(cell);
if (cells) {
Expand Down
2 changes: 1 addition & 1 deletion src/spatRaster.h
Original file line number Diff line number Diff line change
Expand Up @@ -647,7 +647,7 @@ class SpatRaster {
SpatRaster edges(bool classes, std::string type, unsigned directions, double falseval, SpatOptions &opt);
SpatRaster extend(SpatExtent e, std::string snap, double fill, SpatOptions &opt);
std::vector<std::vector<std::vector<double>>> extractVector(SpatVector v, bool touches, std::string method, bool cells, bool xy, bool weights, bool exact, SpatOptions &opt);
std::vector<double> extractVectorFlat(SpatVector v, std::string fun, bool narm, bool touches, std::string method, bool cells, bool xy, bool weights, bool exact, SpatOptions &opt);
std::vector<double> extractVectorFlat(SpatVector v, std::vector<std::string> funs, bool narm, bool touches, std::string method, bool cells, bool xy, bool weights, bool exact, SpatOptions &opt);


std::vector<double> vectCells(SpatVector v, bool touches, std::string method, bool weights, bool exact, SpatOptions &opt);
Expand Down

0 comments on commit 473b782

Please sign in to comment.