Skip to content

Latest commit

 

History

History
629 lines (524 loc) · 35.4 KB

P5.md

File metadata and controls

629 lines (524 loc) · 35.4 KB

Introduction

This code calculates indicator P5 of NorInAliS.

Preparations

Load the sf package (Pebesma 2018):

library(sf)

Download data from the “spatially representative nature monitoring program for terrestrial ecosystems”, or ANO, by its Norwegian acronym (Norwegian Environment Agency 2022):

download.file("https://nedlasting.miljodirektoratet.no/naturovervaking/naturovervaking_eksport.gdb.zip",
              "ANO.gdb.zip")

Extract the layer containing ANO’s survey points:

{
  unzip("ANO.gdb.zip", exdir = "P5")
  ANO <- st_read("P5/Naturovervaking_eksport.gdb", layer = "ANO_SurveyPoint")
  unlink("P5", recursive = TRUE, force = TRUE)
  file.remove("ANO.gdb.zip")
}

## Reading layer `ANO_SurveyPoint' from data source 
##   `/data/Egenutvikling/61308-01_fu_intern_hanno_sandvik/NorInAliS/rmd/P5/Naturovervaking_eksport.gdb' using driver `OpenFileGDB'
## Simple feature collection with 8974 features and 71 fields
## Geometry type: POINT
## Dimension:     XY
## Bounding box:  xmin: -51950 ymin: 6467050 xmax: 1094950 ymax: 7923950
## Projected CRS: ETRS89 / UTM zone 33N

## [1] TRUE

Restrict data to information collected in 2019 and 2020:

years <- 2019:2020
ANO <- ANO[which(ANO$aar %in% years), ]

Exclude inaccessible survey circles:

ANO <- ANO[-which(ANO$utilgjengelig_punkt == "ja"), ]

Check the number of survey points in the selected portion of the ANO dataset:

nrow(ANO)

## [1] 4139

Download data from the Alien Species List 2018 (Sandvik et al. 2020):

fab  <- read.csv2(url("https://datadryad.org/stash/downloads/file_stream/359484"),
                  as.is=T)

Restrict these data to alien plants that are reproducing unaidedly in mainland Norway, and that have been risk-assessed to severe (SE), high (HI) or potentially high (PH) ecological impact:

fab <- fab[which(fab$Kingd == "Plantae" & fab$Status == "reproducing" & 
                 fab$Mainl & fab$Impact %in% c("SE", "HI", "PH")),]

Define auxiliary functions:

# Combines text strings
"%+%" <- function(string1, string2) paste0(string1, string2)


# I just find this more intuitive...
"%contains%" <- function (textstring, searchtext)
  grepl(searchtext, textstring, fixed = TRUE)


# Prepare species names for comparison
prepare.name <- function(x) {
  x <- gsub("_",      " ", x)
  x <- gsub(" × ",    " ", x)
  x <- gsub(" ×",     " ", x)
  x <- gsub(" x ",    " ", x)
  x <- gsub(" \xd7 ", " ", x)
  x <- gsub(" \xd7",  " ", x)
  return(tolower(x))
}

The ANO variable hovedoekosystem_punkt should contain the main ecosystem in each survey point:

table(ANO$hovedoekosystem_punkt, useNA="always")

## 
##                                   annet                          arktisk_tundra                               ferskvann 
##                                       6                                      43                                      17 
##                                   fjell                                     hav                             Nakent berg 
##                                     344                                       1                                       1 
##                           naturlig_apne                      semi_naturlig_mark                                    skog 
##                                      16                                      69                                     351 
##                           Sterkt endret                      sterkt_endret_mark Utilgjengelig punkt i bratt fjellvegg.  
##                                       1                                      19                                       1 
##                                vaatmark                                    <NA> 
##                                     130                                    3140

Translate the main ecosystems (MES) into English:

ANO$MES <- NA
ANO$MES[which(ANO$hovedoekosystem_punkt == "arktisk_tundra")]  <- "Arctic"
ANO$MES[which(ANO$hovedoekosystem_punkt == "ferskvann")]       <- "freshwater"
ANO$MES[which(ANO$hovedoekosystem_punkt == "fjell")]           <- "alpine"
ANO$MES[which(ANO$hovedoekosystem_punkt == "hav")]             <- "marine"
ANO$MES[which(ANO$hovedoekosystem_punkt == "Nakent berg")]     <- "alpine"
ANO$MES[which(ANO$hovedoekosystem_punkt == "naturlig_apne")]   <- "open lowlands"
ANO$MES[which(ANO$hovedoekosystem_punkt == "semi_naturlig_mark")] <- 
                                                                  "semi-natural"
ANO$MES[which(ANO$hovedoekosystem_punkt == "skog")]            <- "woodlands"
ANO$MES[which(ANO$hovedoekosystem_punkt == "sno_og_issystemer")] <- 
                                                                  "snow/ice"
ANO$MES[which(ANO$hovedoekosystem_punkt == "Sterkt endret")]   <- "strongly altered"
ANO$MES[which(ANO$hovedoekosystem_punkt == "sterkt_endret_mark")] <- 
                                                                  "strongly altered"
ANO$MES[which(ANO$hovedoekosystem_punkt == "vaatmark")]        <- "wetlands"
ANO$MES[which(ANO$hovedoekosystem_punkt ==
              "Utilgjengelig punkt i bratt fjellvegg. ")]      <- "inaccessible"
table(ANO$MES, useNA="always")

## 
##           alpine           Arctic       freshwater     inaccessible           marine    open lowlands     semi-natural 
##              345               43               17                1                1               16               69 
## strongly altered         wetlands        woodlands             <NA> 
##               20              130              351             3146

For some reason, the information is missing for the majority of survey points. This seems to be a problem that applies to the first two years of ANO data. So we now describe code in two subsections, one with code that should work starting from 2021, and one for 2019 and 2020, which are used in the baseline estimates.

Code for future use (2021 and onwards)

This code has been tested for ANO data from 2021 and should hopefully work for future years as well. Note that this code is here only shown and not run!

Restrict the dataset to the relevant main ecosystems:

ANO <- ANO[which(ANO$MES %in% c("alpine", "Arctic", "open lowlands",
                                "semi-natural", "wetlands", "woodlands")), ]

Check how many survey points are left after we have excluded the irrelevant ones:

nrow(ANO)

Alien species are recorded in the variable fa_registrert (and two or more species are delimited using ” + “). This allows to count the number of alien species per ANO survey circle:

AlienSpecies <- c()
ANO$number_of_alien_species <- 0
for (i in 1:nrow(ANO)) {
  if (!is.na(ANO$fa_registrert[i])) {
    spec <- unlist(strsplit(ANO$fa_registrert[i], " + ", fixed = TRUE))
    ANO$number_of_alien_species[i] <- length(spec)
    AlienSpecies <- c(AlienSpecies, spec)
  }
}

It might happen that an alien species has been recorded in the variable art_alle_registrert, but that it has not been listed in fa_registrert. To correct for such oversights, we need to compare the recorded names with the Alien Species List:

ANOnames <- prepare.name(ANO$art_alle_registrert)
for (i in prepare.name(fab$Name)) {
  w <- which(ANOnames %contains% i)
  if (length(w)) {
    for (j in w) {
      if (!(i %in% prepare.name(ANO$fa_registrert[j]))) {
        if (is.na(ANO$fa_registrert[j])) {
          ANO$fa_registrert[j] <- i
        } else {
          ANO$fa_registrert[j] <- ANO$fa_registrert[j] %+% " + " %+% i
        }
        v <- which(prepare.name(AlienSpecies) %contains% i)
        if (length(v)) {
          i <- AlienSpecies[v[1]]
        }
        AlienSpecies <- c(AlienSpecies, i)
        ANO$number_of_alien_species[j] <- ANO$number_of_alien_species[j] + 1
      }
    }
  }
}
rm(ANOnames)

It may happen that an alien species cover > 0 is reported without an alien species name, or vice versa. It is more likely that missing values are an oversight than that reported values are erroneous. That’s at least prudent to assume. We therefore adjust the number of alien species according to the cover variable and vice versa (minimum estimates in both cases, i.e. assuming 1 species where none has been reported, and a cover of 0.1% where none has been reported):

ANO$number_of_alien_species[         which(ANO$fa_total_dekning > 0)] <-
  sapply(ANO$number_of_alien_species[which(ANO$fa_total_dekning > 0)], 
         max, 1, na.rm = TRUE)
ANO$fa_total_dekning[         which(ANO$number_of_alien_species > 0)] <-
  sapply(ANO$fa_total_dekning[which(ANO$number_of_alien_species > 0)], 
         max, 0.1, na.rm = TRUE)

Code for the baseline estimate (2019 and 2020)

The code in this subsection is run.

We can try to fill in the missing main ecosystems using other ANO variables. Let’s use the variable kartleggingsenhet_250m2, which contains the ecosystem mapping units for survey circles, following the “Nature in Norway” system (see Halvorsen et al. 2020):

ANO$MES[which(ANO$kartleggingsenhet_250m2 == "ferskvann")]     <- "freshwater"
ANO$MES[which(ANO$kartleggingsenhet_250m2 == "hav")]           <- "marine"
ANO$MES[which(substr(ANO$kartleggingsenhet_250m2,1,1) == "F")] <- "freshwater"
ANO$MES[which(substr(ANO$kartleggingsenhet_250m2,1,1) == "H")] <- "marine"
ANO$MES[which(substr(ANO$kartleggingsenhet_250m2,1,1) == "I")] <- "ice/snow"
ANO$MES[which(substr(ANO$kartleggingsenhet_250m2,1,1) == "L")] <- "freshwater"
ANO$MES[which(substr(ANO$kartleggingsenhet_250m2,1,1) == "M")] <- "marine"
ANO$MES[which(substr(ANO$kartleggingsenhet_250m2,1,1) == "O")] <- "freshwater"
ANO$MES[which(substr(ANO$kartleggingsenhet_250m2,1,1) == "V")] <- "wetlands"
ANO$MES[which(substr(ANO$kartleggingsenhet_250m2 %+% "-", 1, 3) %in%
                c("L4-",  "M8-" ))]                            <- "wetlands"
ANO$MES[which(substr(ANO$kartleggingsenhet_250m2 %+% "-", 1, 3) %in%
                c("T2-",  "T6-",  "T8-" ))]                    <- "open lowlands"
ANO$MES[which(substr(ANO$kartleggingsenhet_250m2 %+% "-", 1, 4) %in%
                c("T11-", "T12-", "T15-", "T18-", "T20-",
                  "T21-", "T23-", "T24-", "T25-", "T29-"))]    <- "open lowlands"
ANO$MES[which(substr(ANO$kartleggingsenhet_250m2 %+% "-", 1, 3) %in%
                c("T1-",  "T3-",  "T5-",  "T7-" ))]            <- "alpine"
ANO$MES[which(substr(ANO$kartleggingsenhet_250m2 %+% "-", 1, 4) %in%
                c("T13-", "T14-", "T16-", "T17-", "T19-",
                  "T22-", "T26-", "T27-"))]                    <- "alpine"
ANO$MES[which(substr(ANO$kartleggingsenhet_250m2 %+% "-", 1, 3) %in%
                c("T4-",  "V2-",  "V8-" ))]                    <- "woodlands"
ANO$MES[which(substr(ANO$kartleggingsenhet_250m2 %+% "-", 1, 4) %in%
                c("T30-"))]                                    <- "woodlands"
ANO$MES[which(substr(ANO$kartleggingsenhet_250m2 %+% "-", 1, 3) %in%
                c("T9-" ))]                                    <- "Arctic"
ANO$MES[which(substr(ANO$kartleggingsenhet_250m2 %+% "-", 1, 4) %in%
                c("T10-", "T28-"))]                            <- "Arctic"
ANO$MES[which(substr(ANO$kartleggingsenhet_250m2 %+% "-", 1, 3) %in%
                c("V9-" ))]                                    <- "semi-natural"
ANO$MES[which(substr(ANO$kartleggingsenhet_250m2 %+% "-", 1, 4) %in%
                c("T31-", "T32-", "T33-", "T34-", "V10-"))]    <- "semi-natural"
ANO$MES[which(substr(ANO$kartleggingsenhet_250m2 %+% "-", 1, 4) %in%
                ("T" %+% (35:45) %+% "-"))]                    <- "strongly altered"
ANO$MES[which(substr(ANO$kartleggingsenhet_250m2 %+% "-", 1, 4) %in%
                c("V11-", "V12-", "V13-"))]                    <- "strongly altered"
table(ANO$MES, useNA="always")

## 
##           alpine           Arctic       freshwater         ice/snow     inaccessible           marine    open lowlands 
##              979               43               27                2                1               11               69 
##     semi-natural strongly altered         wetlands        woodlands             <NA> 
##              295              190              632             1772              118

Still, some missing values. We can get a few more from kartleggingsenhet_1m2, which contains the ecosystem mapping units for the (centres of) ANO survey points:

ANO$MES[which(is.na(ANO$MES) &
              substr(ANO$kartleggingsenhet_1m2, 1, 1) == "F")] <- "freshwater"
ANO$MES[which(is.na(ANO$MES) & 
              substr(ANO$kartleggingsenhet_1m2, 1, 1) == "H")] <- "marine"
ANO$MES[which(is.na(ANO$MES) & 
              substr(ANO$kartleggingsenhet_1m2, 1, 1) == "I")] <- "ice/snow"
ANO$MES[which(is.na(ANO$MES) & 
              substr(ANO$kartleggingsenhet_1m2, 1, 1) == "L")] <- "freshwater"
ANO$MES[which(is.na(ANO$MES) & 
              substr(ANO$kartleggingsenhet_1m2, 1, 1) == "M")] <- "marine"
ANO$MES[which(is.na(ANO$MES) & 
              substr(ANO$kartleggingsenhet_1m2, 1, 1) == "O")] <- "freshwater"
ANO$MES[which(is.na(ANO$MES) & 
              substr(ANO$kartleggingsenhet_1m2, 1, 1) == "V")] <- "wetlands"
ANO$MES[which((is.na(ANO$MES) | ANO$MES == "freshwater") & 
              substr(ANO$kartleggingsenhet_1m2 %+% "-", 1, 3) %in%
                c("L4-" ))]                            <- "wetlands"
ANO$MES[which((is.na(ANO$MES) | ANO$MES == "marine") & 
              substr(ANO$kartleggingsenhet_1m2 %+% "-", 1, 3) %in%
                c("M8-" ))]                            <- "wetlands"
ANO$MES[which(is.na(ANO$MES) &
              substr(ANO$kartleggingsenhet_1m2 %+% "-", 1, 3) %in%
                c("T2-",  "T6-",  "T8-" ))]                    <- "open lowlands"
ANO$MES[which(is.na(ANO$MES) &
              substr(ANO$kartleggingsenhet_1m2 %+% "-", 1, 4) %in%
                c("T11-", "T12-", "T15-", "T18-", "T20-",
                  "T21-", "T23-", "T24-", "T25-", "T29-"))]    <- "open lowlands"
ANO$MES[which(is.na(ANO$MES) &
              substr(ANO$kartleggingsenhet_1m2 %+% "-", 1, 3) %in%
                c("T1-",  "T3-",  "T5-",  "T7-" ))]            <- "alpine"
ANO$MES[which(is.na(ANO$MES) &
              substr(ANO$kartleggingsenhet_1m2 %+% "-", 1, 4) %in%
                c("T13-", "T14-", "T16-", "T17-", "T19-",
                  "T22-", "T26-", "T27-"))]                    <- "alpine"
ANO$MES[which((is.na(ANO$MES) | ANO$MES == "wetlands") &
              substr(ANO$kartleggingsenhet_1m2 %+% "-", 1, 3) %in%
                c("T4-",  "V2-",  "V8-" ))]                    <- "woodlands"
ANO$MES[which(is.na(ANO$MES) &
              substr(ANO$kartleggingsenhet_1m2 %+% "-", 1, 4) %in%
                c("T30-"))]                                    <- "woodlands"
ANO$MES[which(is.na(ANO$MES) &
              substr(ANO$kartleggingsenhet_1m2 %+% "-", 1, 3) %in%
                c("T9-" ))]                                    <- "Arctic"
ANO$MES[which(is.na(ANO$MES) &
              substr(ANO$kartleggingsenhet_1m2 %+% "-", 1, 4) %in%
                c("T10-", "T28-"))]                            <- "Arctic"
ANO$MES[which((is.na(ANO$MES) | ANO$MES == "wetlands") &
              substr(ANO$kartleggingsenhet_1m2 %+% "-", 1, 3) %in%
                c("V9-" ))]                                    <- "semi-natural"
ANO$MES[which((is.na(ANO$MES) | ANO$MES == "wetlands") &
              substr(ANO$kartleggingsenhet_1m2 %+% "-", 1, 4) %in%
                c("T31-", "T32-", "T33-", "T34-", "V10-"))]    <- "semi-natural"
ANO$MES[which(is.na(ANO$MES) & 
              substr(ANO$kartleggingsenhet_1m2 %+% "-", 1, 4) %in%
                ("T" %+% (35:45) %+% "-"))]                    <- "strongly altered"
ANO$MES[which((is.na(ANO$MES) | ANO$MES == "wetlands") & 
              substr(ANO$kartleggingsenhet_1m2 %+% "-", 1, 4) %in%
                c("V11-", "V12-", "V13-"))]                    <- "strongly altered"
table(ANO$MES, useNA="always")

## 
##           alpine           Arctic       freshwater         ice/snow     inaccessible           marine    open lowlands 
##              980               43               24                2                1               11               69 
##     semi-natural strongly altered         wetlands        woodlands             <NA> 
##              300              190              606             1803              110

There are still 110 survey points left for which we were unable to find the main ecosystem. We have to exclude those, in addition to inaccessible points, main ecosystems where we do not expect vascular plants (freshwater, ice/snow, marine, rock) or were we are not interested in alien species (strongly altered nature, such as gardens).

ANO <- ANO[which(ANO$MES %in% c("alpine", "Arctic", "open lowlands",
                                "semi-natural", "wetlands", "woodlands")), ]

Check how many survey points are left after we have excluded the irrelevant ones:

nrow(ANO)

## [1] 3801

That’s not too bad.

Check which alien species have been recorded:

table(ANO$fa_registrert, useNA="always")

## 
## <NA> 
## 3801

That’s a let-down. The ANO variable fa_registrert has not been used in 2019 and 2020. As a workaround, we can compare the variable art_alle_registrert, which lists all species recorded in the centre survey point, with the species names in the Alien Species List 2018:

ANO$number_of_alien_species <- 0
AlienSpecies <- c()
ANOnames <- prepare.name(ANO$art_alle_registrert)
for (i in prepare.name(fab$Name)) {
  w <- which(ANOnames %contains% i)
  AlienSpecies <- c(AlienSpecies, rep(i, length(w)))
  ANO$number_of_alien_species[w] <- ANO$number_of_alien_species[w] + 1
  if (length(w)) {
    ANO$fa_registrert[w] <- ifelse(is.na(ANO$fa_registrert[w]),             i,
                                         ANO$fa_registrert[w] %+% " + " %+% i)
  }
}
rm(ANOnames)

Furthermore, alien species may have been mentioned in free text in the variable kommentar_250m2_flate, by their scientific or Norwegian vernacular name. This is how this variable looks like for the relevant ANO circles:

unique(ANO$kommentar_250m2_flate[which(ANO$fa_total_dekning > 0)])

##  [1] NA                                                                                                                                                                                  
##  [2] "Acer campestre (lav risiko)"                                                                                                                                                       
##  [3] "7 cm platanlønn inne i ruta.\n"                                                                                                                                                    
##  [4] "Mye rogn under 0.8 m\nSolbær innen sirkel"                                                                                                                                         
##  [5] "Rogn i feltsjikt. Einer i busksjikt"                                                                                                                                               
##  [6] "Kanskje sitka eller lutz i feltsjiktet."                                                                                                                                           
##  [7] "Liten platanlønn som står inne i ruten. En liten sitkagran står rett utenfor sirkel."                                                                                              
##  [8] "Einer dominerer i busksjikt"                                                                                                                                                       
##  [9] "Sirkelen ligger mellom en hogstflate og en gammel traktorvei."                                                                                                                     
## [10] "Mye sitka eller lutz i feltsjikt og et tre."                                                                                                                                       
## [11] "Einer, gråor, lutzgran i busksjikt"                                                                                                                                                
## [12] "Lutz eller sitka i feltsjikt. Litt død ved i sirkel."                                                                                                                              
## [13] "En ung furu i feltsjikt. Vanskelig å si om det er norsk furu eller bergfuru, begge finnes lengre ned."                                                                             
## [14] "Sitka eller lutz"                                                                                                                                                                  
## [15] "Lutz eller sitka i sirkel."                                                                                                                                                        
## [16] "Relativ stor mengde av «Pinus mugo» i området."                                                                                                                                    
## [17] "Busksjikt domineres av einer\n2% sølvbunke\n1% skogburkne"                                                                                                                         
## [18] "Greiner av ei lutzgran så vidt innenfor."                                                                                                                                          
## [19] "Europeisk edelgran (Abies alba) representeres av koloradoedelgran i fremmedartsregistreringene."                                                                                   
## [20] "Det finnes rødhyll, hundekjeks og fjellflokk som konsekvens av menneskelig aktivitet (en gård som har dumpa stein og andre i sirkelensområde)."                                    
## [21] "Det eneste treslag i tresjiktet er en stående død stamme av furu"                                                                                                                  
## [22] "Hele sirkelen befinner seg i bratt sørvest-vendt terreng."                                                                                                                         
## [23] "Fremmedart: hagerips"                                                                                                                                                              
## [24] "Litt einer og ungbjørk, men de er ikke registrert som problemart her (noe som kan være relevant). Ei lutzgran på vel to meter, samtidig som det er rundt 100 meter til plantefelt."
## [25] "Ett lutzgrantre i sirkel, ca. 1 meter høy. Nærmeste plantefelt er godt over 500 meter unna. "                                                                                      
## [26] "To lutzgraner på to til tre meter i nord."                                                                                                                                         
## [27] "Fire små lutzgraner i sirkelen. Plantefelt drøye 50 meter unna."                                                                                                                   
## [28] "Tre små busker av lutzgran. I underkant av 100 meter til plantefelt."                                                                                                              
## [29] "En lutzgran på nesten 1 meter, over 300 meter fra nærmeste plantefelt. "                                                                                                           
## [30] "En lutzgran på over 2 meter og en på 1 meter innad i sirkel, over 300 meter til nærmeste plantefelt. "                                                                             
## [31] "Usikker på fremmed furuart"                                                                                                                                                        
## [32] "Antar bergfuru. "                                                                                                                                                                  
## [33] "Området har vært åpent på 1970-tallet, så har det blitt plantet enten sitka eller lutzgran i deler av sirkelen. Plottet er mellom en boreal lynghei og en myr."                    
## [34] "Punktet ligg rett aust for eit sitkaplantefelt og det er tydeleg spreiing av sitkagran inn i sirkelen"                                                                             
## [35] "Liten gran i feltsjikt som mest sannsynlig er sitka eller lutz."                                                                                                                   
## [36] "Sitka eller lutz i feltsjikt."                                                                                                                                                     
## [37] "Enten lutz- eller sitkagran"                                                                                                                                                       
## [38] "Lutz eller sitka i feltsjikt."                                                                                                                                                     
## [39] "Mye gråor med lungenever på seg. Går beitedyr i området. Platanlønn i feltsjikt."                                                                                                  
## [40] "Usikker om det er sitka eller lutz."                                                                                                                                               
## [41] "Fremmedart: mispel\nBjørk i busksjiktet"                                                                                                                                           
## [42] "Sitkagran både som vedplante og busk i sirkel. Spredd fra nærliggende plantefelt."                                                                                                 
## [43] "Usikker registrering av fremmedart"                                                                                                                                                
## [44] "Lange forvedete vivendel-individer som har slynget seg rundt andre vekster slik at de overstiger 2 meter. Men ettersom dette er en slyngplante ble den ikke registrert som tre. "  
## [45] "En mispel vokser i tresjiktet (0,1% fremmedart)"                                                                                                                                   
## [46] "Revebjelle og veitistel og trådsiv er andre problemarter som også finnes i sirkelen. Finnes ca 15% død einer i sirkelen, som ikke er tatt med i busksjiktet"                       
## [47] "Revebjelle tatt inn som problemart. Ca halvparten av all eineren er død"                                                                                                           
## [48] "Veitistel som problemart"                                                                                                                                                          
## [49] "Bjørk dominerer i tresjiktet, i ca hogstklasse 4"

We extract the relevant species names:

for (i in 1:7) {
  spec1 <- c("platanlønn", "pinus mugo", "rødhyll",
             "bergfuru", "mispel")[i]
  spec2 <- c("acer pseudoplatanus", "pinus mugo", "sambucus racemosa",
             "pinus uncinata", "cotoneaster spec.")[i]
  w <- which(prepare.name(ANO$kommentar_250m2_flate) %contains% spec1)
  if (length(w)) {
    for (j in w) {
      if (is.na(ANO$fa_registrert[j])) {
        ANO$fa_registrert[j] <- spec2
        AlienSpecies <- c(AlienSpecies, spec2)
        ANO$number_of_alien_species[j] <- ANO$number_of_alien_species[j] + 1
      } else {
        if (!(ANO$fa_registrert[j] %contains% spec2)) {
          ANO$fa_registrert[j] <- ANO$fa_registrert[j] %+% " + " %+% spec2
          AlienSpecies <- c(AlienSpecies, spec2)
          ANO$number_of_alien_species[j] <- ANO$number_of_alien_species[j] + 1
        }
      }
    }
  }
}

In quite some cases, “Lutz or Sitka spruce” were reported. These should be counted as records of a single species. We arbitrarily choose Sitka spruce:

w <- which(prepare.name(ANO$kommentar_250m2_flate) %contains% "sitka" |
           prepare.name(ANO$kommentar_250m2_flate) %contains% "lutz")
if (length(w)) {
  for (j in w) {
    if (is.na(ANO$fa_registrert[j])) {
      ANO$fa_registrert[j] <- "picea sitchensis"
      AlienSpecies <- c(AlienSpecies, "picea sitchensis")
      ANO$number_of_alien_species[j] <- ANO$number_of_alien_species[j] + 1
    } else {
      if (!(ANO$fa_registrert[j] %contains% "picea sitchensis" |
            ANO$fa_registrert[j] %contains% "picea lutzii"  )) {
        ANO$fa_registrert[j] <- ANO$fa_registrert[j] %+% " + " %+%
                                "picea sitchensis"
        AlienSpecies <- c(AlienSpecies, "picea sitchensis")
        ANO$number_of_alien_species[j] <- ANO$number_of_alien_species[j] + 1
      }
    }
  }
}

Check the available ANO data on alien species:

table(ANO$fa_total_dekning > 0, ANO$number_of_alien_species, useNA="always")

##        
##            0    1    2 <NA>
##   FALSE 3692    1    0    0
##   TRUE    51   38    1    0
##   <NA>    18    0    0    0

This table shows that there are 51 cases in which the reported alien species cover is greater than 0 but where no alien species name has been recorded, as well as one case in which an alien species name has been recorded but the reported alien species cover is 0. We therefore adjust the number of alien species according to the cover variable and vice versa:

ANO$number_of_alien_species[         which(ANO$fa_total_dekning > 0)] <-
  sapply(ANO$number_of_alien_species[which(ANO$fa_total_dekning > 0)], 
         max, 1, na.rm = TRUE)
ANO$fa_total_dekning[         which(ANO$number_of_alien_species > 0)] <-
  sapply(ANO$fa_total_dekning[which(ANO$number_of_alien_species > 0)], 
         max, 0.1, na.rm = TRUE)

Upper-case first letters in species names:

AlienSpecies <- toupper(substr(AlienSpecies, 1, 1)) %+% substr(AlienSpecies, 2, 72)

Calculations

This section definitely works now (i.e. for the baseline estimate), but it should also work in the future (from 2021 onwards), given that the relevant ANO variables keep their current names, definitions and usage.

Show the number of alien species recorded per ANO survey point:

table(ANO$number_of_alien_species, useNA="always")

## 
##    0    1    2 <NA> 
## 3710   90    1    0

These figures are not entirely reliable because not all alien species names seem to have been recorded.

The alien species recorded were (with the same reservations as above, and the additional one that some P. lutzii have been recorded as P. sitchensis):

table(AlienSpecies)

## AlienSpecies
## Acer pseudoplatanus   Cotoneaster spec.  Epilobium hirsutum        Picea lutzii    Picea sitchensis          Pinus mugo 
##                   6                   2                   1                   3                  24                   1 
##      Pinus uncinata   Sambucus racemosa 
##                   2                   2

Now, let’s calculate the baseline estimates of the three indicator definitions.

P5(a) - average number of alien species recorded in survey circles of the spatially representative nature monitoring program (with the reservation that the underlying figures are not reliable, see above):

x <- sum(ANO$number_of_alien_species, na.rm = TRUE)
N <- nrow(ANO)
cat("P5(a): " %+% round(x / N, 5) %+% " ± " %+%
    round(sqrt(x * (1 - x / N)) / N, 5) %+% " (mean ± standard deviation)\n")

## P5(a): 0.0242 ± 0.00249 (mean ± standard deviation)

P5(b) - proportion of survey circles of the spatially representative nature monitoring program in which at least one alien species is recorded:

x <- length(which(ANO$fa_total_dekning > 0))
N <- nrow(ANO)
cat("P5(b): " %+% round(100 * x / N, 3) %+% "% ± " %+%
    round(100 * sqrt(x * (1 - x / N)) / N, 3) %+% "% (mean ± standard deviation)\n")

## P5(b): 2.394% ± 0.248% (mean ± standard deviation)

P5(c) - average cumulative coverage of alien species recorded in survey circles of the spatially representative nature monitoring program:

cat("P5(c): " %+% 
    round(sum(ANO$fa_total_dekning, na.rm = TRUE) / nrow(ANO), 4) %+% "%\n")

## P5(c): 0.1442%

Confidence levels for P5(b):

conf <-  qbinom(c(0.025, 0.25, 0.5, 0.75, 0.975), N, x / N) / N
names(conf) <- (c(0.025, 0.25, 0.5, 0.75, 0.975) * 100) %+% "%CL"
print(conf)

##     2.5%CL      25%CL      50%CL      75%CL    97.5%CL 
## 0.01920547 0.02236254 0.02394107 0.02551960 0.02893975

Disaggregation of P5(b) for main ecosystems:

{
  tab <- table(ANO$MES[ANO$fa_total_dekning > 0])
  cat("Number of ANO survey circles with alien species:\n")
  print(tab)
  cat("\n\nProportion, i.e. indicator definition P5(b) by ecosystem:\n")
  print(tab / table(ANO$MES)[names(tab)])
  cat("\n\nStandard deviations:\n")
  print(sqrt(tab * (1 - tab / table(ANO$MES)[names(tab)])) /
        table(ANO$MES)[names(tab)])
}

## Number of ANO survey circles with alien species:
## 
##        alpine open lowlands  semi-natural      wetlands     woodlands 
##             2             2            37             8            42 
## 
## 
## Proportion, i.e. indicator definition P5(b) by ecosystem:
## 
##        alpine open lowlands  semi-natural      wetlands     woodlands 
##   0.002040816   0.028985507   0.123333333   0.013201320   0.023294509 
## 
## 
## Standard deviations:
## 
##        alpine open lowlands  semi-natural      wetlands     woodlands 
##   0.001441602   0.020196623   0.018984399   0.004636461   0.003552309