Reputation: 1
Does anybody know how to solve this problem? I'm trying to build a species Distribution model using bioclimatic variables
sdm
package by Naimi, 2016
R version 4.4.1
ERROR:
model <- sdm(Species ~ ., data = sdm_data,
methods = c('glm', 'gam', 'gbm', 'rf', 'svm', 'mars'))
Error in x@presence : no applicable method for
@
applied to an object of class "NULL"
Part of code:
bioclim_files <- list.files(pattern = "*.tif$", full.names = TRUE)
Study_Area <- st_read("shp/3Province.shp")
DEM <- rast ("shp/DEM.tif")
DEM_crop <- crop (DEM, Study_Area)
DEM_mask <- mask (DEM_crop, Study_Area)
Bio <- rast(bioclim_files)
Bio <- crop (Bio, Study_Area)
Bio <- mask (Bio, Study_Area)
ext(Bio)
ext(DEM)
Bio_crop <- crop(Bio, ext(DEM))
Bio_resample <- resample(Bio_crop, DEM) #Bio1_2_4_8_15_18
occurance_data <- import("p_i.xlsx")
sdm_data <- sdmData(Species ~ . + coords(Lon + Lat),
train = occurance_data,
predictors = Bio_resample)
print(sdm_data)
summary(sdm_data)
model <- sdm(Species ~ ., data = sdm_data,
methods = c('glm', 'gam', 'gbm', 'rf', 'svm', 'mars'))
str(sdm_data)
occurance_data more details:
> names(occurance_data)
[1] "OBJECTID" "Species" "Lon" "Lat"
> str(occurance_data)
'data.frame': 78 obs. of 4 variables:
$ OBJECTID: num 1 2 3 4 5 6 7 8 9 10 ...
$ Species : chr "p_i" "p_i" "p_i" "p_i" ...
$ Lon : num 50.8 50.8 50.9 51.3 51.3 ...
$ Lat : num 36.7 36.7 36.7 36.4 36.7 ...
> summary(occurance_data)
OBJECTID Species Lon Lat
Min. : 1.00 Length:78 Min. :49.01 Min. :36.12
1st Qu.:20.25 Class :character 1st Qu.:50.86 1st Qu.:36.29
Median :39.50 Mode :character Median :52.36 Median :36.42
Mean :39.50 Mean :51.97 Mean :36.56
3rd Qu.:58.75 3rd Qu.:53.09 3rd Qu.:36.76
Max. :78.00 Max. :55.59 Max. :37.39
I've tried capital letters like 'Species' or 'species', even added more occurrence data but none of them worked.
Upvotes: 0
Views: 77
Reputation: 226741
Based on the output of str(occurance_data)
, it looks like you have a data set where the Species
variable is a character vector describing which species was observed at a particular location. If we look at the help file for sdmData
it strongly suggests that data containing multi-species records are supposed to be provided in wide format, i.e. a 0/1 column for each species:
sdmData
creates a data object, for single or multiple species. It can automatically detect the variables containing species data (if a data.frame is provided in ‘train’), but it is recommended to use formula through which all species (in the left hand side, e.g.,sp1+sp2+sp3 ~ .
)
This is confirmed by looking at the data used for example 3 in ?sdmData
:
file <- system.file("external/multi_pa_df.csv", package="sdm")
df <- read.csv(file)
str(df)
'data.frame': 150 obs. of 16 variables:
$ b15 : num 26 54.5 27 32.8 42.8 ...
$ NDVI : num 195 110 108 93 179 ...
$ categoric1: chr "A" "B" "B" "E" ...
$ categoric2: chr "ff" "cc" "bb" "cc" ...
$ x : int 494375 214375 364375 564375 94375 634375 444375 624375 64375 224375 ...
$ y : int 4774936 4244936 4674936 4344936 4744936 4474936 4354936 4314936 4714936 4664936 ...
$ sp1 : int 1 0 1 1 1 1 1 1 1 1 ...
$ sp2 : int 0 0 0 0 0 0 0 0 0 1 ...
$ sp3 : int 0 0 0 0 1 1 1 0 1 1 ...
$ sp4 : int 0 0 0 0 1 0 1 0 1 1 ...
$ sp5 : int 1 1 1 1 0 1 0 1 0 0 ...
$ sp6 : int 0 0 0 0 0 0 0 0 0 0 ...
$ sp7 : int 0 0 0 0 0 0 0 0 0 0 ...
$ sp8 : int 0 1 0 0 1 0 0 0 1 0 ...
$ sp9 : int 1 1 1 1 0 1 1 1 0 1 ...
$ sp10 : int 0 0 1 1 1 1 0 1 1 0 ...
You would probably have to tell us more about the structure of your data before we can help. Is it a presence-only data set, i.e. you have recorded which species did occur at a particular location (and you can infer that all species in your species list not in the data set were not recorded at that location)? It should be possible to transform your data set from long to wide, but it could be a little bit tricky. In particular, suppose that at location x1, y1
, you recorded species 1, 2, and 3 (but not 4, 5, 6). Would your data set for that location be recorded as
Species xloc yloc <other covariates>
p1 x1 y1 ...
p2 x1 y1 [identical]
p3 x1 y1 [identical]
?
I think the way I would do this, roughly, is
species, x, y
and another with x, y, covariates
species, x, y
, data set to a x + y + presence-absence
data set (e.g. see here or here)merge()
(base R) or full_join
(tidyverse) to combine the presence-absence data set with unique(covariate_dataset)
Upvotes: 1