From d913c8b8ed1773109366efaffc58e6f0a06b0be5 Mon Sep 17 00:00:00 2001 From: Georges Kunstler <Georges.Kunstler@gmail.com> Date: Tue, 3 Sep 2013 15:55:38 +1000 Subject: [PATCH] new version of competition function to US Spain Swiss --- R/FUN.TRY.R | 22 ++++--- R/format.function.R | 25 ++++---- merge.data.CANADA.R | 3 +- merge.data.SPAIN.R | 114 ++++++++++++++++++------------------- merge.data.SWISS.R | 23 ++++---- merge.data.US.R | 9 +-- ms/data.format.md | 3 + ms/table.data.progress.ods | Bin 13580 -> 13803 bytes 8 files changed, 105 insertions(+), 94 deletions(-) diff --git a/R/FUN.TRY.R b/R/FUN.TRY.R index d101206..2252d66 100644 --- a/R/FUN.TRY.R +++ b/R/FUN.TRY.R @@ -89,7 +89,7 @@ fun.extract.try <- function(ObservationID.t, data, Non.Trait.Data, Trait.Data) { names(TF.exp.data) <- "TF.exp.data" res.temp <- data.frame(ObservationID = ObservationID.t, AccSpeciesName = unique(data.temp$AccSpeciesName), t(Vec.Non.Trait.Data), TF.exp.data, t(Vec.Trait.Data.OrigValue), t(Vec.Trait.Data.OrigUnit), - t(Vec.Trait.Data.StdValue)) + t(Vec.Trait.Data.StdValue), stringsAsFactors =FALSE) return(res.temp) } @@ -227,8 +227,12 @@ fun.turn.list.in.DF <- function(sp, res.list) { data.genus <- t(sapply(sp, FUN = function(i, res.list) res.list[[i]]$genus, res.list = res.list)) data.nobs <- t(sapply(sp, FUN = function(i, res.list) res.list[[i]]$nobs, res.list = res.list)) ## create data.frame withh all observation - extract.species.try <- data.frame(data.mean, data.sd, data.exp, data.genus, data.nobs) - names(extract.species.try) <- c(paste(c("Leaf.N", "Seed.mass", "SLA", "Wood.Density"), "mean", sep = "."), paste(c("Leaf.N", "Seed.mass", "SLA", "Wood.Density"), "sd", sep = "."), paste(c("Leaf.N", "Seed.mass", "SLA", "Wood.Density"), "exp", sep = "."), paste(c("Leaf.N", "Seed.mass", "SLA", "Wood.Density"), "genus", sep = "."), paste(c("Leaf.N", "Seed.mass", "SLA", "Wood.Density"), "nobs", sep = ".")) + extract.species.try <- data.frame(data.mean, data.sd, data.exp, data.genus, data.nobs, stringsAsFactors =FALSE) + names(extract.species.try) <- c(paste(c("Leaf.N", "Seed.mass", "SLA", "Wood.Density"), "mean", sep = "."), + paste(c("Leaf.N", "Seed.mass", "SLA", "Wood.Density"), "sd", sep = "."), + paste(c("Leaf.N", "Seed.mass", "SLA", "Wood.Density"), "exp", sep = "."), + paste(c("Leaf.N", "Seed.mass", "SLA", "Wood.Density"), "genus", sep = "."), + paste(c("Leaf.N", "Seed.mass", "SLA", "Wood.Density"), "nobs", sep = ".")) return(extract.species.try) } @@ -252,7 +256,11 @@ fun.extract.format.sp.traits.TRY <- function(sp, sp.syno.table, data) { ##### TRANSFORM LIST IN A TABLE extract.species.try <- fun.turn.list.in.DF(sp, res.list) - + + ##### TODO ADD A TEST OF GOOD EXTRACTION OF TRAITS + test.num <- sample(1:length(sp),1) + if( extract.species.try[test.num,"SLA.mean"] != fun.species.traits(sp[test.num], species.table = sp.syno.table, + traits = traits, data = data)$mean[grep("SLA",traits)]) stop('traits value not good for the species in extraction from TRY') ############### add mean sd of species or genus if we want to use that sd.vec.sp <- readRDS(file = "./data/process/sd.vec.sp.rds") sd.vec.genus <- readRDS(file = "./data/process/sd.vec.genus.rds") @@ -262,8 +270,8 @@ fun.extract.format.sp.traits.TRY <- function(sp, sp.syno.table, data) { genus.names <- paste(c("Leaf.N", "Seed.mass", "SLA", "Wood.Density"), "genus", sep = ".") ### add columns - extract.species.try.2 <- data.frame(extract.species.try, extract.species.try[, - sd.names]) + extract.species.try.2 <- data.frame(extract.species.try, + extract.species.try[,sd.names], stringsAsFactors =FALSE) ## update value sd.names.1 <- paste(sd.names, 1, sep = ".") @@ -272,7 +280,7 @@ fun.extract.format.sp.traits.TRY <- function(sp, sp.syno.table, data) { extract.species.try.2[[sd.names.1[i]]][extract.species.try.2[[genus.names[i]]]] <- sd.vec.genus[i] } data.frame.TRY <- data.frame(sp = sp, Latin_name = sp.syno.table[["Latin_name_syn"]], - extract.species.try.2) + extract.species.try.2, stringsAsFactors =FALSE) if (sum(!data.frame.TRY[["sp"]] == sp) > 0) stop("Wrong order of species code") return(data.frame.TRY) diff --git a/R/format.function.R b/R/format.function.R index 0526a8b..6b7fa86 100644 --- a/R/format.function.R +++ b/R/format.function.R @@ -62,6 +62,7 @@ BA.fun <- function(diam,weights){ ##' @return data frame with obs.id and one column per species with basal area of the species (without the target tree) ##' @author Kunstler BA.SP.FUN <- function(obs.id,diam,sp,id.plot,weights,weight.full.plot){ +print(length(obs.id)) require(data.table) id.plot <- as.character(id.plot) obs.id <- as.character(obs.id) @@ -194,6 +195,7 @@ return(BA.SP.FUN.XY(obs.id[census==census.id],xy.table[census==census.id,],diam[ ### wrapping function to run BA.SP.FUN.XY per census BA.SP.FUN.XY.census <- function(census,obs.id,xy.table,diam,sp,Rlim,parallel=FALSE,rpuDist=FALSE){ unique.census <- unique(census) +print(unique.census) res.list <- lapply(unique.census,FUN=BA.SP.FUN.XY.l,obs.id,xy.table,diam,sp,Rlim,parallel,rpuDist) res.mat <- rbind.fill(res.list ) res.mat <- res.mat[match(obs.id,rownames(res.mat)),] @@ -264,6 +266,7 @@ if(is.null(data.tot[['weights']])) stop("Please create a weights vector, even if require(data.table) data.tot <- data.table(data.tot) data <- data.tot[ecocode==ecoregion,] +print(dim(data)) rm(data.tot) data.BA.SP <- BA.SP.FUN.census(census=data[['census']], obs.id=as.vector(data[['obs.id']]), @@ -296,17 +299,17 @@ setkeyv(data,"obs.id") if(sum(!data.BA.sp[["obs.id"]] == data[["obs.id"]]) >0) stop("competition index not in the same order than data") ##### ## ADD TRY DATA OR TRAITS IF NEEDED -if(!is.na(data.TRY)){ -sp.extract <- species.lookup[species.lookup[["sp"]] %in% unique(data[["sp"]]),] -data.traits <- fun.extract.format.sp.traits.TRY(sp=sp.extract[["sp"]],sp.syno.table=sp.extract,data.TRY) -### TO DO ADD OPTION TO INCLUE OTHER DATA on MAX HEIGHT -## save everything as a list -print(dim(data.traits)) -list.temp <- list(data.tree=data,data.BA.SP=data.BA.sp,data.traits=data.traits) -save(list.temp,file=paste("./data/process/list",name.country,ecoregion,"Rdata",sep=".")) +if(is.data.frame(data.TRY)){ + sp.extract <- species.lookup[species.lookup[["sp"]] %in% unique(data[["sp"]]),] + data.traits <- fun.extract.format.sp.traits.TRY(sp=sp.extract[["sp"]],sp.syno.table=sp.extract,data.TRY) + ### TO DO ADD OPTION TO INCLUE OTHER DATA on MAX HEIGHT + ## save everything as a list + print(dim(data.traits)) + list.temp <- list(data.tree=data,data.BA.SP=data.BA.sp,data.traits=data.traits) + save(list.temp,file=paste("./data/process/list",name.country,ecoregion,"Rdata",sep=".")) }else{ -list.temp <- list(data.tree=data,data.BA.SP=data.BA.sp,data.traits=NA) -saveRDS(list.temp,file=paste("./data/process/list",name.country,ecoregion,"Rdata",sep=".")) + list.temp <- list(data.tree=data,data.BA.SP=data.BA.sp,data.traits=NA) + saveRDS(list.temp,file=paste("./data/process/list",name.country,ecoregion,"Rdata",sep=".")) } } @@ -336,7 +339,7 @@ if(sum(!colnames(BA.SP.temp)==as.character((levels(data.tree.s[['sp']]))))>0) st ### compute sum per row BATOT <- apply(BA.SP.temp,MARGIN=1,FUN=sum) -data.res <- data.frame(obs.id=data.tree.s[['obs.id']],BA.SP.temp,BATOT=BATOT) +data.res <- data.frame(obs.id=data.tree.s[['obs.id']],BA.SP.temp,BATOT=BATOT, stringsAsFactors =FALSE) return(data.res) } diff --git a/merge.data.CANADA.R b/merge.data.CANADA.R index 4abfd33..8711afb 100644 --- a/merge.data.CANADA.R +++ b/merge.data.CANADA.R @@ -1,11 +1,10 @@ ### MERGE canada DATA Edited by FH rm(list = ls()) source("./R/format.function.R") +source("./R/FUN.TRY.R") library(reshape) ######################### READ DATA read individuals tree data data.canada <- -######################### read.csv('./data/raw/DataCanada/Canada_Data2George_20130816.csv',header=TRUE,stringsAsFactors -######################### =FALSE) data.canada <- read.csv("./data/raw/DataCanada/Canada_Data2George_20130818.csv", header = TRUE, stringsAsFactors = FALSE) data.canada <- data.canada[which(!is.na(data.canada$Species)), ] diff --git a/merge.data.SPAIN.R b/merge.data.SPAIN.R index 7da9b81..15eb6a9 100644 --- a/merge.data.SPAIN.R +++ b/merge.data.SPAIN.R @@ -1,6 +1,7 @@ ### MERGE spain DATA Edited by FH rm(list = ls()) source("./R/format.function.R") +source("./R/FUN.TRY.R") library(reshape) ######################### READ DATA read individuals tree data data.spain <- @@ -18,22 +19,9 @@ res.quant.boot <- t(sapply(levels(factor(data.spain[["SP_code"]])), FUN = f.quan ## create data base data.max.height <- data.frame(code = rownames(res.quant.boot), Max.height.mean = res.quant.boot[, - 1], Max.height.sd = res.quant.boot[, 2], Max.height.nobs = res.quant.boot[, 3]) + 1], Max.height.sd = res.quant.boot[, 2], Max.height.nobs = res.quant.boot[, 3], stringsAsFactors =FALSE) rm(res.quant.boot) write.csv(data.max.height, file = "./data/process/data.max.height.spain.csv") # I was planning to save processed data in that folder -# ## merge TRY with max height merge.TRY <- -# merge(merge.TRY,data.max.height,by='code') rm(data.max.height) ## use mean sd -# of max tree height over all species merge.TRY$Max.height.sd.1 <- -# rep(mean(merge.TRY[['Max.height.sd']],na.rm=TRUE),length=nrow(merge.TRY)) ### -# keep only variables needed in traits data names.traits.data <- -# c('code','Latin_name','Leaf.N.mean','Seed.mass.mean','SLA.mean','Wood.Density.mean', -# 'Leaf.Lifespan.mean','Max.height.mean','Leaf.N.sd.1','Seed.mass.sd.1','SLA.sd.1', -# 'Wood.Density.sd.1', 'Leaf.Lifespan.sd.1','Max.height.sd.1') data.traits <- -# merge.TRY[,names.traits.data] names(data.traits) <- -# c('sp','Latin_name','Leaf.N.mean','Seed.mass.mean','SLA.mean','Wood.Density.mean', -# 'Leaf.Lifespan.mean','Max.height.mean','Leaf.N.sd','Seed.mass.sd','SLA.sd', -# 'Wood.Density.sd', 'Leaf.Lifespan.sd','Max.height.sd') ## rename to have -# standard variables name rm(merge.TRY,names.traits.data) ################################################################ FORMAT INDIVIDUAL TREE DATA @@ -42,11 +30,14 @@ data.spain$G <- data.spain[["adbh"]] ## diameter growth in mm per year data.spain$year <- data.spain[["years"]] ## number of year between measurement - MISSING data.spain$D <- data.spain[["dbh1"]]/10 ## diameter in mm convert to cm data.spain$dead <- as.numeric(data.spain[["Life_status"]] == "dead") ## dummy variable for dead tree 0 alive 1 dead - MIGHT WANT TO CHANGE THIS TO BE BASED ON MORTALITY_CUT -data.spain$sp <- as.character(data.spain[["SP_code"]]) ## species code +data.spain$sp <- paste("sp",(data.spain[["SP_code"]]) ,sep=".") ## species code +data.spain$sp.name <- data.spain[["SP_name"]] data.spain$plot <- (data.spain[["Plot_ID_SFI"]]) ## plot code data.spain$htot <- data.spain[["ht1"]] ## height of tree in m data.spain$tree.id <- data.spain$Tree_ID_SFI ## tree unique id - +data.spain$obs.id <- as.character(1:nrow(data.spain)) ## obs uniquue id +data.spain$census <- rep(1,nrow(data.spain)) ## only one census in spain +data.spain$weights <- as.vector(1/(pi * (data.spain[["R1"]])^2)) ## weights in 1/m^2 #### change coordinates system of x y to be in lat long WGS84 library(sp) library(dismo) @@ -80,14 +71,14 @@ table(data.spain$eco_code) ## There's an eco-region with no code, and one with < 1000 sites The former we ## could drop as they were on the border of Spain +### PLOT ECOREGION library(RColorBrewer) mycols <- brewer.pal(10, "Set3") - ecoreg <- unclass(data.spain$eco_code) +pdf("./figs/ecoregion.spain.pdf") plot(data.spain[["CX"]][order(ecoreg)], data.spain[["CY"]][order(ecoreg)], pty = ".", cex = 0.2, col = rep(mycols, as.vector(table(ecoreg)))) - legend("topleft", col = mycols, legend = levels(data.spain$eco_code), pch = rep(19, length(levels(ecoreg))), cex = 2) points(data.spain[["CX"]][ecoreg == 9], data.spain[["CY"]][ecoreg == 9], pty = ".", @@ -97,56 +88,65 @@ points(data.spain[["CX"]][ecoreg == 1], data.spain[["CY"]][ecoreg == 1], pty = " cex = 0.5, col = "black") ## Highlight the 'rare' ecoregions PA1219 looks to be similar to PA1209, merge ## them together +dev.off() + +## merge data.spain$eco_codemerged <- combine_factor(data.spain$eco_code, c(1:8, 6, 9)) data.spain <- data.spain[-which(data.spain$eco_codemerged == ""), ] -###################### PERCENT DEAD variable percent dead/cannot do with since dead variable is -###################### missing compute numer of dead per plot to remove plot with disturbance +##### +## PLOT of MERGED ECOREGION +## mycols <- brewer.pal(9, "Set3") +## plot(data.spain[["CX"]][order(data.spain$eco_codemerged)], data.spain[["CY"]][order(data.spain$eco_codemerged)], pty = ".", +## cex = 0.2, col = rep(mycols, as.vector(table(data.spain$eco_codemerged)))) +## legend("topleft", col = mycols, legend = levels(data.spain$eco_codemerged), pch = rep(19, +## length(levels(data.spain$eco_codemerged))), cex = 2) + +###################### PERCENT DEAD +###################### compute numer of dead per plot to remove plot with disturbance perc.dead <- tapply(data.spain[["dead"]], INDEX = data.spain[["plot"]], FUN = function.perc.dead) table(data.spain$dead) ## VARIABLE TO SELECT PLOT WITH NOT BIG DISTURBANCE KEEP OFTHER VARIABLES IF ## AVAILABLE (disturbance record) -data.spain <- merge(data.spain, data.frame(plot = as.numeric(names(perc.dead)), perc.dead = perc.dead), - sort = FALSE, by = "plot") +data.spain <- merge(data.spain, data.frame(plot = as.numeric(names(perc.dead)), perc.dead = perc.dead, stringsAsFactors =FALSE), + sort = FALSE, by = "plot") ########################################################### PLOT SELECTION FOR THE ANALYSIS Remove data with mortality == 1 or 2 -table(data.spain$Mortality_Cut) -data.spain <- subset(data.spain, subset = (data.spain[["Mortality_Cut"]] == 0 | data.spain[["Mortality_Cut"]] == - "")) +data.spain <- subset(data.spain, + subset = (data.spain[["Mortality_Cut"]] == 0 | + data.spain[["Mortality_Cut"]] == "")) colnames(data.spain)[colnames(data.spain) %in% c("mat", "pp", "PET")] <- c("MAT", "PP", "PET") colnames(data.spain)[names(data.spain) == "eco_codemerged"] <- c("ecocode") vec.abio.var.names <- c("MAT", "PP", "PET") -vec.basic.var <- c("tree.id", "sp", "sp.name", "plot", "ecocode", "D", "G", "dead", - "year", "htot", "Lon", "Lat", "perc.dead") -data.tree <- subset(data.spain, select = c(vec.basic.var, vec.abio.var.names)) -save(data.spain, file = "./data/process/datspain.RData") - -############################################## COMPUTE MATRIX OF COMPETITION INDEX WITH SUM OF BA PER SPECIES IN EACH PLOT in -############################################## m^2/ha without the target species -data.BA.SP <- BA.SP.FUN(id.tree = as.vector(data.spain[["tree.id"]]), diam = as.vector(data.spain[["D"]]), - sp = as.vector(data.spain[["sp"]]), id.plot = as.vector(data.spain[["plot"]]), - weights = as.vector(1/(pi * (data.spain[["R1"]])^2)), weight.full.plot = 1/(pi * - (25)^2)) - -## change NA and <0 data for 0 -data.BA.SP[which(is.na(data.BA.SP), arr.ind = TRUE)] <- 0 -data.BA.SP[, -1][which(data.BA.SP[, -1] < 0, arr.ind = TRUE)] <- 0 - -### CHECK IF sp and sp name for column are the same -if (sum(!(names(data.BA.SP)[-1] %in% unique(data.spain[["sp"]]))) > 0) stop("competition index sp name not the same as in data.tree") - -#### compute BA tot for all competitors -BATOT.COMPET <- apply(data.BA.SP[, -1], MARGIN = 1, FUN = sum, na.rm = TRUE) -data.BA.SP$BATOT.COMPET <- BATOT.COMPET -### create data frame -names(data.BA.SP) <- c("tree.id", names(data.BA.SP)[-1]) -data.BA.sp <- merge(data.frame(tree.id = dataIFN.spain[["tree.id"]], ecocode = dataIFN.spain[["ecocode"]]), - data.BA.SP, by = "tree.id", sort = FALSE) -## test -if (sum(!data.BA.sp[["tree.id"]] == data.tree[["tree.id"]]) > 0) stop("competition index not in the same order than data.tree") - -## save everything as a list -list.spain <- list(data.tree = data.tree, data.BA.SP = data.BA.sp, data.traits = data.traits) -save(list.spain, file = "./data/process/list.spain.Rdata") +vec.basic.var <- c("tree.id","obs.id", "sp", "sp.name", "plot", "ecocode", "D", "G", "dead", + "year", "htot", "Lon", "Lat", "perc.dead","census","weights") +data.spain <- subset(data.spain, select = c(vec.basic.var, vec.abio.var.names)) + + + + +############################################## +############################################## +#################### GENERATE ONE OBJECT PER ECOREGION + +# vector of ecoregion name +ecoregion.unique <- unique(data.spain[["ecocode"]]) +sum(data.spain[["ecocode"]] == ecoregion.unique[1]) + +### read TRY data +TRY.DATA.FORMATED <- readRDS("./data/process/TRY.DATA.FORMATED.rds") + +## create lookup table for spain +species.lookup <- data.frame(sp=data.spain[!duplicated(data.spain[["sp"]]),"sp"], + Latin_name=data.spain[!duplicated(data.spain[["sp"]]),"sp.name"], + Latin_name_syn=data.spain[!duplicated(data.spain[["sp"]]),"sp.name"], + stringsAsFactors =FALSE) + + +#### lapply function to generate data per ecoregion +system.time(lapply(ecoregion.unique[1:2], FUN = fun.data.per.ecoregion, data.tot = data.spain, + plot.name = "plot", weight.full.plot = NA, name.country = "Spain", data.TRY = TRY.DATA.FORMATED, + species.lookup = species.lookup)) + diff --git a/merge.data.SWISS.R b/merge.data.SWISS.R index 2efc7a5..58ed741 100644 --- a/merge.data.SWISS.R +++ b/merge.data.SWISS.R @@ -59,9 +59,9 @@ res.quant.boot <- t(sapply(levels(factor(data.swiss[["spcode"]])), FUN = f.quant ## create data base data.max.height <- data.frame(code = rownames(res.quant.boot), Max.height.mean = res.quant.boot[, - 1], Max.height.sd = res.quant.boot[, 2], Max.height.nobs = res.quant.boot[, 3]) + 1], Max.height.sd = res.quant.boot[, 2], Max.height.nobs = res.quant.boot[, 3], stringsAsFactors =FALSE) rm(res.quant.boot) -# write.csv(data.max.height,file='./data/process/data.max.height.swiss.csv') +write.csv(data.max.height,file='./data/process/data.max.height.swiss.csv') ########################################## FORMAT INDIVIDUAL TREE DATA change unit and names of variables to be the same ########################################## in all data for the tree @@ -83,7 +83,7 @@ data.swiss$ecocode <- rep("A", nrow(data.swiss)) perc.dead <- tapply(data.swiss[["dead"]], INDEX = data.swiss[["plot"]], FUN = function.perc.dead) # ## VARIABLE TO SELECT PLOT WITH NOT BIG DISTURBANCE KEEP OTHER VARIABLES IF # AVAILABLE (disturbance record) -data.swiss <- merge(data.swiss, data.frame(plot = names(perc.dead), perc.dead = perc.dead), +data.swiss <- merge(data.swiss, data.frame(plot = names(perc.dead), perc.dead = perc.dead, stringsAsFactors =FALSE), by = "plot", sort = FALSE) ########################################################### PLOT SELECTION FOR THE ANALYSIS Remove data with dead == 1 @@ -94,15 +94,12 @@ data.climate <- data.climate[, c(1, 7, 15:19)] data.climate$MAP <- apply(data.climate[, 4:7], 1, sum) data.swiss <- merge(data.swiss, data.frame(siteid = data.climate$CLNR, swb = data.climate$swb_100, - MAT = data.climate$tave_68, MAP = data.climate$MAP), sort = F, all.x = T) + MAT = data.climate$tave_68, MAP = data.climate$MAP, stringsAsFactors =FALSE), sort = F, all.x = T) rm(data.climate) -############################################## COMPUTE MATRIX OF COMPETITION INDEX WITH SUM OF BA PER SPECIES IN EACH PLOT in -############################################## m^2/ha without the target species -data.BA.SP <- BA.SP.FUN.census(census=data.swiss[["census"]],obs.id=data.swiss[["obs.id"]],diam=data.swiss[["D"]],sp=data.swiss[["sp"]],id.plot=data.swiss[["plot"]],weights=data.swiss[["weights"]],weight.full.plot=NA) - -## check if good order - sum(! (data.BA.SP[,"obs.id"]) == data.swiss[["obs.id"]]) +############################################## +############################################## +#################### GENERATE ONE OBJECT PER ECOREGION # vector of ecoregion name ecoregion.unique <- unique(data.swiss[["ecocode"]]) @@ -114,11 +111,11 @@ TRY.DATA.FORMATED <- readRDS("./data/process/TRY.DATA.FORMATED.rds") ## create lookup table for swiss species.lookup <- data.frame(sp=data.swiss[!duplicated(data.swiss[["sp"]]),"sp"], Latin_name=data.swiss[!duplicated(data.swiss[["sp"]]),"sp.name"], - Latin_name_syn=data.swiss[!duplicated(data.swiss[["sp"]]),"sp.name"]) + Latin_name_syn=data.swiss[!duplicated(data.swiss[["sp"]]),"sp.name"], stringsAsFactors =FALSE) -#### lapply function -(lapply(ecoregion.unique, FUN = fun.data.per.ecoregion, data.tot = data.swiss, +#### lapply function to generate data for each ecoregion +system.time(lapply(ecoregion.unique, FUN = fun.data.per.ecoregion, data.tot = data.swiss, plot.name = "plot", weight.full.plot = NA, name.country = "Swiss", data.TRY = TRY.DATA.FORMATED, species.lookup = species.lookup)) diff --git a/merge.data.US.R b/merge.data.US.R index 275c7c1..399f931 100644 --- a/merge.data.US.R +++ b/merge.data.US.R @@ -41,7 +41,8 @@ data.us$htot <- rep(NA, length(data.us[["Species"]])) ## height of tree in m - data.us$tree.id <- as.character(data.us$TreeID) ## tree unique id data.us$sp.name <- NA - +## census is missing use as only one census and check with mark +data.us$census <- rep(1,nrow(data.us)) ### add plot weights for computation of competition index (in 1/m^2) data.us$weights <- 1/(10000 * data.us[["PlotSize"]]) @@ -68,7 +69,7 @@ for (i in 1:length(sel.small.div)) { perc.dead <- tapply(data.us[["dead"]], INDEX = data.us[["plot"]], FUN = function.perc.dead) # ## VARIABLE TO SELECT PLOT WITH NOT BIG DISTURBANCE KEEP OFTHER VARIABLES IF # AVAILABLE (disturbance record) -data.us <- merge(data.us, data.frame(plot = names(perc.dead), perc.dead = perc.dead), +data.us <- merge(data.us, data.frame(plot = names(perc.dead), perc.dead = perc.dead, stringsAsFactors = FALSE), by = "plot", sort = FALSE) @@ -86,7 +87,7 @@ data.us[["sp"]] <- paste("sp", data.us[["sp"]], sep = ".") ## variables to keep vec.abio.var.names <- c("MAT", "MAP") vec.basic.var <- c("tree.id", "sp", "plot", "subplot", "ecocode", "D", "G", "dead", - "year", "htot", "Lon", "Lat", "perc.dead", "weights") + "year", "htot", "Lon", "Lat", "perc.dead", "weights","census") data.tree <- subset(data.us, select = c(vec.basic.var, vec.abio.var.names)) rm(data.us) ## creat row unique id @@ -103,6 +104,6 @@ ecoregion.unique <- unique(data.tree[["ecocode"]]) #### lapply function -system.time(lapply(ecoregion.unique, FUN = fun.data.per.ecoregion, data.tot = data.tree, +system.time(lapply(ecoregion.unique[3], FUN = fun.data.per.ecoregion, data.tot = data.tree, plot.name = "subplot", weight.full.plot = NA, name.country = "US", data.TRY = TRY.DATA.FORMATED, species.lookup = species.clean)) diff --git a/ms/data.format.md b/ms/data.format.md index 8f42907..1dd2df4 100644 --- a/ms/data.format.md +++ b/ms/data.format.md @@ -14,6 +14,7 @@ For the analysis we need for each ecoregion country (or big tropical plot) a lis * First element is a data.frame for individual tree data with columns + - $obs.id4 a unique identifier of observqtion (if multiple observation for a same tree) - $tree.id$ a unique identifier of each tree - $sp$ the species code - $plot$ the plot code @@ -22,10 +23,12 @@ For the analysis we need for each ecoregion country (or big tropical plot) a lis - $G$ the diameter growth rate in mm / yr. - $dead$ a dummy variable 0 alive 1 dead - $year$ the number of year for the growth measurement + - $census$ the name of the year of the census 1 - $htot$ the height of the individual (m) for the data base for which it is availble to compute max height per species - $Lon$ Longitude of the plot in WGS84 - $Lat$ Latitude of teh plots in WGS84 - $perc.dead$ the percentage of dead computed on each plot to exlude plot with perturbation (equal 1 for plot with known perturbation) + - $weights$ the weigths of teh tree to have an estimation of basal area per m^2 (so 1/(m^2)) - then the potential abiotic variables that we can use in the analysis * Second element is a data.frame competition index with columns diff --git a/ms/table.data.progress.ods b/ms/table.data.progress.ods index 45ad7a04fb61990b230d2d804cdfdd98e5175b1e..066e23e01c71741e74cd25e4e18686f32392640e 100644 GIT binary patch delta 11558 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 G@Bagq_I{uM delta 11316 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 -- GitLab