-
-
Save grosscol/bc40383a3de09987548757208d4d75fb to your computer and use it in GitHub Desktop.
### Refactored Birds in Trees code | |
library(dplyr) | |
library(mefa4) | |
# Function to create list of list of args for outer calculation function | |
# returns List of list(stand_id, species_list, stand_data) | |
make_stand_args <- function(stand_id, data){ | |
splist <- data %>% | |
filter(StandID == stand_id) %>% | |
dplyr::select(Species) %>% | |
distinct()%>% | |
pull(Species) | |
result <- list(stand_id = stand_id, | |
species_list = splist) | |
return(result) | |
} | |
# Function to do the inner calculation | |
# calc the mden of single species, | |
# given duration and distance intervals of all species, and tau lookup table | |
calc_mden <- function(species_id, dur_intervals, dis_intervals, tau_ref){ | |
# duration variable phi for species | |
y_dur <- as.matrix(dur_intervals[[species_id]]) | |
d_dur <- matrix(c(3, 5, 10), nrow(y_dur), 3, byrow=TRUE, | |
dimnames=dimnames(y_dur)) | |
# distance variable tau | |
y_dis <- as.matrix(dis_intervals[[species_id]]) | |
d_dis <- matrix(c(0.5, 1), nrow(y_dis), 2, byrow=TRUE, | |
dimnames=dimnames(y_dis)) | |
# grab tau for specific species | |
tau <- tau_ref[which(tau_ref$Sp == species_id),3] | |
rmax <- apply(d_dis, 1, max) | |
q <- (tau^2 / rmax^2) * (1-exp(-(rmax/tau)^2)) | |
A <- pi * rmax^2 | |
a_q <- A * q | |
y_total <- rowSums(y_dur) | |
m_den <- mean(y_total/a_q$tau_best) | |
return(m_den) | |
} | |
# Outer calculation function | |
# return a list of mdens for each stand | |
# Each list of mdens would have one entry for each species. | |
calc_stand_mdens <- function(stand_id, species_list, tau_ref, all_dis, all_dur){ | |
names(species_list) <- species_list | |
species_mdens <- lapply(X=species_list, FUN=calc_mden, | |
dur_intervals=all_dur, dis_intervals=all_dis, | |
tau_ref=tau_ref) | |
return(species_mdens) | |
} | |
# Wrap do.call because I hate trying to stuff it into lapply directly. | |
# Combine dynamic and static args into single arguments list | |
splat_wrapper <- function(dynamic_args, static_args){ | |
args <- c(dynamic_args, static_args) | |
do.call(what=calc_stand_mdens, args=args) | |
} | |
# Input Parameters | |
raw_data <- source('~/Downloads/SampleBirdData.txt')$value | |
tau_ref <- source('~/Downloads/tau_ref.txt')$value | |
stand_list <- source('~/Downloads/sample_standlist.txt')$value | |
# Correct column is a list of lists issue in source data | |
qpadbirdData <- raw_data | |
qpadbirdData$Species <- unlist(raw_data$Species, use.names=F) | |
# Calculate the crosstabs for distance and duration for all species | |
# time Intervals | |
all_dur <- mefa4::Xtab(~ VisitID + Dur + Species, qpadbirdData) | |
# distance intervals | |
all_dis <- mefa4::Xtab(~ VisitID + Dis + Species, qpadbirdData) | |
# Create static args list of the tau_refs and crosstabs | |
static_args <- list(tau_ref=tau_ref, | |
all_dur=all_dur, | |
all_dis=all_dis) | |
# Given a list of stands and the source data, | |
# make a list of arguments lists for the calculation function | |
dynamic_args <- lapply(X = stand_list, | |
FUN = make_stand_args, | |
data = qpadbirdData) | |
# Now run the foo function once for each element (set of args) from stand_args | |
names(stand_args) <- stand_list | |
stand_calcs <- lapply(X = dynamic_args, | |
FUN = splat_wrapper, | |
static_args = static_args) |
c("BEF 15", "NUL 10", "BEF 16", "NUL 2", "BEF 17", "NUL 8", "BEF 14", | |
"NUL 14", "NUL 1", "NUL 13", "NUL 15", "NUL 6", "BEF 11", "BEF 3", | |
"NUL 3", "BEF 2", "BEF 8", "NUL 4", "BEF 9", "BEF 7", "NUL 9", | |
"NUL 7", "NUL 5", "BEF 1", "NUL 12", "NUL 11", "BEF 6", "BEF 12" | |
) |
structure(list(StandID = c("BEF 15", "NUL 10", "BEF 16", "NUL 2", | |
"BEF 17", "NUL 8", "BEF 17", "BEF 17", "BEF 14", "NUL 14", "NUL 1", | |
"NUL 13", "NUL 15", "NUL 6", "NUL 13", "BEF 11", "BEF 14", "NUL 15", | |
"BEF 16", "BEF 3", "NUL 14", "BEF 3", "BEF 14", "NUL 3", "BEF 11", | |
"BEF 2", "NUL 2", "BEF 16", "BEF 8", "BEF 3", "BEF 8", "NUL 4", | |
"BEF 9", "BEF 17", "BEF 7", "NUL 14", "BEF 17", "NUL 10", "NUL 4", | |
"NUL 13", "NUL 9", "NUL 10", "BEF 3", "BEF 2", "BEF 3", "NUL 13", | |
"NUL 15", "NUL 6", "NUL 4", "NUL 7", "BEF 11", "NUL 10", "NUL 5", | |
"NUL 9", "BEF 1", "NUL 12", "NUL 5", "BEF 8", "NUL 7", "NUL 8", | |
"BEF 9", "BEF 1", "NUL 2", "NUL 8", "BEF 7", "BEF 8", "BEF 9", | |
"NUL 8", "BEF 8", "NUL 15", "NUL 5", "NUL 14", "BEF 9", "NUL 13", | |
"NUL 10", "NUL 13", "BEF 14", "NUL 8", "NUL 6", "NUL 10", "BEF 17", | |
"BEF 8", "NUL 11", "BEF 6", "BEF 16", "BEF 2", "NUL 7", "NUL 14", | |
"BEF 16", "NUL 5", "NUL 1", "BEF 15", "NUL 9", "BEF 12", "BEF 11", | |
"BEF 14", "NUL 12", "NUL 5", "NUL 14", "NUL 3"), Species = structure(list( | |
Species = c("NOPA", "HETH", "REVI", "RBNU", "BTNW", "MYWA", | |
"OVEN", "BTNW", "WIWR", "BLBW", "BTNW", "HETH", "SCTA", "YBSA", | |
"RBNU", "BLBW", "GCKI", "BTBW", "REVI", "REVI", "REVI", "REVI", | |
"RBNU", "REVI", "OVEN", "OVEN", "HETH", "REVI", "BLBW", "RCKI", | |
"BTBW", "OVEN", "VEER", "BTNW", "BCCH", "REVI", "WIWR", "BCCH", | |
"OVEN", "BLJA", "YBSA", "MYWA", "BTNW", "BCCH", "PAWA", "BTBW", | |
"NOFL", "REVI", "YBSA", "REVI", "CSWA", "SOSP", "BTNW", "REVI", | |
"BTBW", "BOCH", "YBSA", "CAWA", "BTNW", "HETH", "DEJU", "HETH", | |
"WTSP", "YBSA", "BTBW", "BLJA", "VEER", "REVI", "BTBW", "BTNW", | |
"REVI", "BTBW", "BTBW", "YBSA", "AMRE", "RUGR", "BBCU", "RBNU", | |
"BLBW", "REVI", "BTBW", "NAWA", "BTBW", "GCKI", "BCCH", "RBNU", | |
"HETH", "OVEN", "BTNW", "BLBW", "REVI", "REVI", "REVI", "ALFL", | |
"COYE", "HETH", "REVI", "SWTH", "OVEN", "REVI")), row.names = c(NA, | |
-100L), class = c("tbl_df", "tbl", "data.frame")), Dur = c("5-10min", | |
"0-3min", "0-3min", "5-10min", "5-10min", "5-10min", "0-3min", | |
"5-10min", "0-3min", "3-5min", "5-10min", "0-3min", "0-3min", | |
"3-5min", "0-3min", "0-3min", "5-10min", "0-3min", "0-3min", | |
"5-10min", "3-5min", "5-10min", "0-3min", "0-3min", "0-3min", | |
"0-3min", "3-5min", "5-10min", "0-3min", "0-3min", "0-3min", | |
"0-3min", "0-3min", "0-3min", "0-3min", "0-3min", "0-3min", "3-5min", | |
"0-3min", "0-3min", "3-5min", "0-3min", "0-3min", "0-3min", "3-5min", | |
"0-3min", "5-10min", "0-3min", "3-5min", "0-3min", "0-3min", | |
"0-3min", "0-3min", "3-5min", "0-3min", "0-3min", "5-10min", | |
"0-3min", "0-3min", "0-3min", "0-3min", "0-3min", "0-3min", "5-10min", | |
"0-3min", "5-10min", "3-5min", "5-10min", "3-5min", "3-5min", | |
"5-10min", "0-3min", "0-3min", "0-3min", "0-3min", "0-3min", | |
"3-5min", "5-10min", "3-5min", "0-3min", "0-3min", "0-3min", | |
"0-3min", "0-3min", "0-3min", "0-3min", "0-3min", "0-3min", "5-10min", | |
"0-3min", "0-3min", "0-3min", "0-3min", "0-3min", "0-3min", "5-10min", | |
"0-3min", "0-3min", "0-3min", "0-3min"), Dis = c("0-50m", "50-100m", | |
"50-100m", "0-50m", "50-100m", "50-100m", "0-50m", "0-50m", "50-100m", | |
"50-100m", "0-50m", "50-100m", "0-50m", "50-100m", "50-100m", | |
"0-50m", "50-100m", "50-100m", "50-100m", "50-100m", "50-100m", | |
"50-100m", "0-50m", "0-50m", "0-50m", "50-100m", "50-100m", "0-50m", | |
"50-100m", "0-50m", "50-100m", "50-100m", "0-50m", "50-100m", | |
"50-100m", "50-100m", "50-100m", "50-100m", "50-100m", "50-100m", | |
"50-100m", "50-100m", "50-100m", "0-50m", "50-100m", "0-50m", | |
"0-50m", "50-100m", "50-100m", "0-50m", "50-100m", "50-100m", | |
"50-100m", "50-100m", "50-100m", "0-50m", "0-50m", "0-50m", "0-50m", | |
"0-50m", "0-50m", "50-100m", "50-100m", "0-50m", "0-50m", "50-100m", | |
"0-50m", "50-100m", "50-100m", "50-100m", "50-100m", "50-100m", | |
"0-50m", "0-50m", "0-50m", "50-100m", "0-50m", "0-50m", "50-100m", | |
"0-50m", "0-50m", "50-100m", "0-50m", "0-50m", "0-50m", "0-50m", | |
"0-50m", "50-100m", "0-50m", "50-100m", "0-50m", "50-100m", "50-100m", | |
"50-100m", "50-100m", "0-50m", "0-50m", "50-100m", "0-50m", "50-100m" | |
), VisitID = c("BEF 15 A 182", "NUL 10 A 154", "BEF 16 B 160", | |
"NUL 2 D 172", "BEF 17 D 158", "NUL 8 B 154", "BEF 17 B 182", | |
"BEF 17 C 202", "BEF 14 B 158", "NUL 14 B 193", "NUL 1 B 197", | |
"NUL 13 D 152", "NUL 15 B 150", "NUL 6 D 173", "NUL 13 A 152", | |
"BEF 11 A 159", "BEF 14 A 182", "NUL 15 B 150", "BEF 16 C 160", | |
"BEF 3 A 179", "NUL 14 F 152", "BEF 3 D 179", "BEF 14 B 182", | |
"NUL 3 D 197", "BEF 11 E 159", "BEF 2 E 162", "NUL 2 C 172", | |
"BEF 16 C 180", "BEF 8 A 180", "BEF 3 B 179", "BEF 8 A 180", | |
"NUL 4 A 196", "BEF 9 C 160", "BEF 17 F 158", "BEF 7 E 180", | |
"NUL 14 D 176", "BEF 17 F 182", "NUL 10 D 194", "NUL 4 A 196", | |
"NUL 13 E 193", "NUL 9 C 195", "NUL 10 F 194", "BEF 3 F 179", | |
"BEF 2 E 162", "BEF 3 C 162", "NUL 13 C 193", "NUL 15 D 150", | |
"NUL 6 C 173", "NUL 4 C 196", "NUL 7 A 154", "BEF 11 C 159", | |
"NUL 10 D 154", "NUL 5 B 196", "NUL 9 A 154", "BEF 1 D 202", | |
"NUL 12 B 153", "NUL 5 D 196", "BEF 8 F 180", "NUL 7 B 154", | |
"NUL 8 C 154", "BEF 9 C 204", "BEF 1 E 179", "NUL 2 A 155", "NUL 8 D 174", | |
"BEF 7 D 180", "BEF 8 E 180", "BEF 9 A 180", "NUL 8 A 195", "BEF 8 C 160", | |
"NUL 15 E 150", "NUL 5 B 155", "NUL 14 B 176", "BEF 9 A 180", | |
"NUL 13 D 193", "NUL 10 B 175", "NUL 13 F 176", "BEF 14 A 158", | |
"NUL 8 C 154", "NUL 6 C 155", "NUL 10 E 194", "BEF 17 D 202", | |
"BEF 8 F 180", "NUL 11 F 194", "BEF 6 A 178", "BEF 16 C 160", | |
"BEF 2 B 162", "NUL 7 B 174", "NUL 14 D 193", "BEF 16 D 180", | |
"NUL 5 B 196", "NUL 1 D 172", "BEF 15 C 158", "NUL 9 D 154", | |
"BEF 12 F 159", "BEF 11 D 159", "BEF 14 B 201", "NUL 12 E 153", | |
"NUL 5 A 155", "NUL 14 C 193", "NUL 3 E 172")), row.names = c(NA, | |
-100L), class = c("tbl_df", "tbl", "data.frame")) |
structure(list(Sp = c("RTHU", "BLBW", "GCKI", "BOCH", "BTBW", | |
"BRCR", "MAWA", "CMWA", "BAWW", "AMRE", "BHVI", "NOPA", "CSWA", | |
"CAWA", "BTNW", "MOWA", "WIWR", "REVI", "YBFL", "RBGR", "LEFL", | |
"PAWA", "BLPW", "DOWO", "YBSA", "OVEN", "DEJU", "CEDW", "SCTA", | |
"VEER", "SOSP", "MYWA", "EAWP", "BCCH", "WBNU", "SWSP", "INBU", | |
"BEKI", "NAWA", "HAWO", "ALFL", "GCFL", "AMGO", "WTSP", "SWTH", | |
"LISP", "PUFI", "RCKI", "AMRO", "BLJA", "RBNU", "COYE", "RUGR", | |
"NOWA", "HETH", "BBCU", "NOFL", "PIWO"), tau = c(0.298999, 0.470045, | |
0.388122, 0.474593, 0.452795, 0.464176, 0.607747, 0.5223915, | |
0.615874, 0.6017003, 0.560901, 0.563834, 0.747081, 0.625857, | |
0.595276, 0.777684, 0.590151, 0.69453, 0.633242, 0.931138, 0.769924, | |
0.631699821, 0.631699821, 0.6087145, 0.802057, 0.798386, 0.618904, | |
0.7378935, 0.676319, 0.918361, 0.603962, 0.681626, 0.837621, | |
0.8056039, 0.743488, 0.932883, 0.702112, 0.818148, 0.689438, | |
0.782298, 0.978404, 0.914948, 0.836709, 1.169883, 0.7810633, | |
0.777799, 0.794372, 0.898033, 0.929143, 1.074654, 0.932979, 0.770593, | |
1.10043, 0.723556, 1.27119, 1.88797, 1.37911, 1.45686), tau_best = c(0.2110982, | |
0.364099, 0.379388, 0.409157, 0.447038, 0.449505, 0.452729, 0.460238, | |
0.461154, 0.4969422, 0.513969, 0.535236, 0.535671, 0.536698, | |
0.537636, 0.537947, 0.545593, 0.550853, 0.58209, 0.58465, 0.589032, | |
0.595738, 0.595738, 0.601205, 0.608763, 0.612224, 0.621086, 0.62365, | |
0.631127, 0.666315, 0.66755, 0.677063, 0.706598, 0.7102644, 0.713479, | |
0.719708, 0.747621, 0.751698, 0.753327, 0.7644505, 0.7648203, | |
0.767414, 0.780721, 0.792044, 0.7953055, 0.811148, 0.83448, 0.879949, | |
0.918185, 0.918586, 0.93674, 0.942806, 0.955041, 1.09869, 1.22448, | |
1.25339, 1.41392, 1.43079)), class = c("tbl_df", "tbl", "data.frame" | |
), row.names = c(NA, -58L)) |
I think I fixed that issue by adding tau_ref
to the make_stand_args()
function
make_stand_args <- function(stand_id, tau_ref, data){
splist <- data %>%
filter(StandID == stand_id) %>%
dplyr::select(Species) %>%
distinct()
spdata <- data %>%
filter(StandID == stand_id)
result <- list(stand_id = stand_id,
species_list = splist,
stand_data = spdata,
tau_ref = tau_ref)
return(result)
}
Good catch. The invariant argument would need to be added to splat_wrapper
, and the static args added to the dynamic ones. Derp.
Adding it to the args list works. I usually keep those args lists for things that change with each call invocation, but in this case I think your way is simpler.
As for uploading a sample data set, you could upload the output of dput
for a sample of the data as your own gist. The r-help-readme channel probably has a bunch of tips about that.
ok I just uploaded a sample. I am getting an error that says this when you show traceback. it doesn't like the fact that all_dur is a list but if I get stand_calc_mdens
to return all_dur
and then run it seperately and use as.matrix(all_dur[[species_id]]
manually it works fine
Error in h(simpleError(msg, call)) :
error in evaluating the argument 'x' in selecting a method for function 'as.matrix': invalid subscript type 'list'
9.
h(simpleError(msg, call))
8.
.handleSimpleError(function (cond)
.Internal(C_tryCatchHelper(addr, 1L, cond)), "invalid subscript type 'list'",
base::quote(dur_intervals[[species_id]]))
7.
as.matrix(dur_intervals[[species_id]])
6.
FUN(X[[i]], ...)
5.
lapply(X = species_list, FUN = calc_mden, dur_intervals = all_dur,
dis_intervals = all_dis, tau_ref = tau_ref)
4.
(function (stand_id, species_list, stand_data, tau_ref)
{
all_dur <- Xtab(~VisitID + Dur + Species$Species, stand_data)
all_dis <- Xtab(~VisitID + Dis + Species$Species, stand_data) ...
3.
do.call(what = calc_stand_mdens, args = args)
2.
FUN(X[[i]], ...)
1.
lapply(X = stand_args, FUN = splat_wrapper)
@grosscol it doesn't look like it is seing the
tau_ref
argument. I made a sample dataset that you can try to run. is there a way to upload it to this github?