Tracking the consequences of environmental change requires information on both the physical and biological characteristics of ecological systems. Large-scale environmental data are now widely available from many data repositories. However, these data sets often need to be down-scaled in order to be paired with local ecological measurements. Hence, micro-environmental sensors are sometimes useful to integrate scales of ecological information relevant to global change. This is an open-source, collaborative network of micro-environmental sensors deployed globally.
# combine multiple csv files into one dataframe ###
concat <- function(fileList){
dflist <- data.frame() ## create empty dataframe
for(i in 1:length(fileList)){
loadfile<-read.csv(fileList[i]) ## read each csv file for loop
loggerID <- basename(fileList[i]) ## root file name
loggerID = substr(loggerID, 1, nchar(loggerID)-4) ## drop csv
loadfile[,"loggerID"] <- rep(loggerID,nrow(loadfile)) ## add logger ID to column
dflist<-rbind(dflist,loadfile) ## concatenate previous csv to main dataframe
}
return(dflist)
}
## calculates summary statistics of logger data
## includes minimum, maximum, mean, standard deviation, number of observations, start date of logger, end date of logger, duration of logger recording, and response variable.
summary.stat <- function(fileList, resp){
dflist <- data.frame() ## create empty dataframe
## combine into one dataframe
for(i in 1:length(fileList)){
loadfile<-read.csv(fileList[i]) ## read each csv file for loop
loggerID <- basename(fileList[i]) ## root file name
loggerID = substr(loggerID, 1, nchar(loggerID)-4) ## drop csv
## add detailed time statistics
t.str <- strptime(loadfile[,"Date"], "%m/%d/%Y %H:%M")
loadfile[,"days"] <- as.Date(format(t.str, "%m/%d/%Y"), "%m/%d/%Y") ## separate date
loadfile[,"hours"] <- as.numeric(format(t.str, "%H")) ##specify hour logged
loadfile[,"minutes"] <- as.numeric(format(t.str, "%M")) ## specify minutes logged
obs <- nrow(loadfile) ## number of observations
start.date <- min(loadfile[,"days"]) ## day logger first started
end.date <- max(loadfile[,"days"]) ## day logger ended
duration <- as.numeric(difftime(end.date,start.date)) ## duration of logger activity
resp.stat <- function(fileList, resp){
resp.min <- min(fileList[,resp]) ## minimum of response
resp.max <- max(fileList[,resp]) ## maximum of response
resp.mean <- mean(fileList[,resp]) ## mean of response
resp.sd <- mean(fileList[,resp]) ## standard deviation of response
sum.stat <- data.frame(resp.min,resp.max,resp.mean,resp.sd,obs,start.date,end.date,duration,resp)
colnames(sum.stat) <- c("min","max","mean","sd","observations","start.date","end.date","duration","Response")
return(sum.stat)
}
sum.stat <- resp.stat(loadfile, resp)
sum.stat[,"loggerID"] <- loggerID
dflist <- rbind(dflist, sum.stat)
}
return(dflist)
}
## error bar functions
source("errorbar.functions.r")
## load hobo data files
fileList<-list.files("sample.data\\",pattern=".csv$",full=T)
## view file list
fileList
## [1] "sample.data\\Allan_Laroque.csv" "sample.data\\Carrot.csv"
## [3] "sample.data\\Charles_Sule.csv" "sample.data\\Doro_ground.csv"
## [5] "sample.data\\Earth.csv"
## extract summary statistics of light data
Temp.summary <- summary.stat(fileList, "Temperature")
Luxavg.summary <- summary.stat(fileList, "Avg.light")
Luxmax.summary <- summary.stat(fileList, "Max.light")
Total.summary <- rbind(Temp.summary,Luxavg.summary,Luxmax.summary)
Total.summary
## min max mean sd observations start.date
## 1 -5.995 36.187 17.72612 17.72612 3342 2013-04-19
## 2 -6.120 45.452 19.64054 19.64054 3340 2013-05-01
## 3 -4.758 43.844 19.93838 19.93838 3340 2013-05-01
## 4 1.112 46.593 21.70595 21.70595 3340 2013-05-01
## 5 -7.267 44.580 19.15374 19.15374 3340 2013-05-01
## 6 0.000 220445.900 3854.04216 3854.04216 3342 2013-04-19
## 7 0.000 209423.600 19189.79108 19189.79108 3340 2013-05-01
## 8 0.000 253512.800 24466.20401 24466.20401 3340 2013-05-01
## 9 0.000 253512.800 15502.10931 15502.10931 3340 2013-05-01
## 10 0.000 253512.800 19940.18389 19940.18389 3340 2013-05-01
## 11 0.000 220445.900 3854.04216 3854.04216 3342 2013-04-19
## 12 0.000 209423.600 19189.79108 19189.79108 3340 2013-05-01
## 13 0.000 253512.800 24466.20401 24466.20401 3340 2013-05-01
## 14 0.000 253512.800 15502.10931 15502.10931 3340 2013-05-01
## 15 0.000 253512.800 19940.18389 19940.18389 3340 2013-05-01
## end.date duration Response loggerID
## 1 2014-01-22 278 Temperature Allan_Laroque
## 2 2014-02-03 278 Temperature Carrot
## 3 2014-02-03 278 Temperature Charles_Sule
## 4 2014-02-03 278 Temperature Doro_ground
## 5 2014-02-03 278 Temperature Earth
## 6 2014-01-22 278 Avg.light Allan_Laroque
## 7 2014-02-03 278 Avg.light Carrot
## 8 2014-02-03 278 Avg.light Charles_Sule
## 9 2014-02-03 278 Avg.light Doro_ground
## 10 2014-02-03 278 Avg.light Earth
## 11 2014-01-22 278 Max.light Allan_Laroque
## 12 2014-02-03 278 Max.light Carrot
## 13 2014-02-03 278 Max.light Charles_Sule
## 14 2014-02-03 278 Max.light Doro_ground
## 15 2014-02-03 278 Max.light Earth
data.hobo <- concat(fileList)
str(data.hobo)
## 'data.frame': 16702 obs. of 6 variables:
## $ ID : int 1 2 3 4 5 6 7 8 9 10 ...
## $ Date : Factor w/ 3481 levels "1/1/2014 0:00",..: 1369 1370 1371 1372 1373 1374 1375 1381 1384 1385 ...
## $ Temperature: num 25.7 25.1 19.9 17.9 15.3 ...
## $ Avg.light : num 43.1 0 0 0 0 0 0 0 0 0 ...
## $ Max.light : num 43.1 0 0 0 0 0 0 0 0 0 ...
## $ loggerID : chr "Allan_Laroque" "Allan_Laroque" "Allan_Laroque" "Allan_Laroque" ...
head(data.hobo,10)
## ID Date Temperature Avg.light Max.light loggerID
## 1 1 4/19/2013 12:00 25.708 43.1 43.1 Allan_Laroque
## 2 2 4/19/2013 14:00 25.125 0.0 0.0 Allan_Laroque
## 3 3 4/19/2013 16:00 19.853 0.0 0.0 Allan_Laroque
## 4 4 4/19/2013 18:00 17.950 0.0 0.0 Allan_Laroque
## 5 5 4/19/2013 20:00 15.282 0.0 0.0 Allan_Laroque
## 6 6 4/19/2013 22:00 12.690 0.0 0.0 Allan_Laroque
## 7 7 4/20/2013 0:00 10.748 0.0 0.0 Allan_Laroque
## 8 8 4/20/2013 2:00 9.275 0.0 0.0 Allan_Laroque
## 9 9 4/20/2013 4:00 7.882 0.0 0.0 Allan_Laroque
## 10 10 4/20/2013 6:00 6.268 0.0 0.0 Allan_Laroque
tail(data.hobo,10)
## ID Date Temperature Avg.light Max.light loggerID
## 16693 3331 2/2/2014 18:00 21.760 0 0 Earth
## 16694 3332 2/2/2014 20:00 21.760 0 0 Earth
## 16695 3333 2/2/2014 22:00 21.760 0 0 Earth
## 16696 3334 2/3/2014 0:00 21.664 0 0 Earth
## 16697 3335 2/3/2014 2:00 21.664 0 0 Earth
## 16698 3336 2/3/2014 4:00 21.664 0 0 Earth
## 16699 3337 2/3/2014 6:00 21.664 0 0 Earth
## 16700 3338 2/3/2014 8:00 21.569 0 0 Earth
## 16701 3339 2/3/2014 10:00 21.664 0 0 Earth
## 16702 3340 2/3/2014 12:00 21.760 0 0 Earth
## separate date from hours and minutes
t.str <- strptime(data.hobo[,"Date"], "%m/%d/%Y %H:%M") ## format is month/day/year hour:minute
data.hobo[,"days"] <- as.Date(format(t.str, "%m/%d/%Y"), "%m/%d/%Y") ## separate date
data.hobo[,"hours"] <- as.numeric(format(t.str, "%H")) ##specify hour logged
data.hobo[,"minutes"] <- as.numeric(format(t.str, "%M")) ## specify minutes logged
head(data.hobo, 10)
## ID Date Temperature Avg.light Max.light loggerID
## 1 1 4/19/2013 12:00 25.708 43.1 43.1 Allan_Laroque
## 2 2 4/19/2013 14:00 25.125 0.0 0.0 Allan_Laroque
## 3 3 4/19/2013 16:00 19.853 0.0 0.0 Allan_Laroque
## 4 4 4/19/2013 18:00 17.950 0.0 0.0 Allan_Laroque
## 5 5 4/19/2013 20:00 15.282 0.0 0.0 Allan_Laroque
## 6 6 4/19/2013 22:00 12.690 0.0 0.0 Allan_Laroque
## 7 7 4/20/2013 0:00 10.748 0.0 0.0 Allan_Laroque
## 8 8 4/20/2013 2:00 9.275 0.0 0.0 Allan_Laroque
## 9 9 4/20/2013 4:00 7.882 0.0 0.0 Allan_Laroque
## 10 10 4/20/2013 6:00 6.268 0.0 0.0 Allan_Laroque
## days hours minutes
## 1 2013-04-19 12 0
## 2 2013-04-19 14 0
## 3 2013-04-19 16 0
## 4 2013-04-19 18 0
## 5 2013-04-19 20 0
## 6 2013-04-19 22 0
## 7 2013-04-20 0 0
## 8 2013-04-20 2 0
## 9 2013-04-20 4 0
## 10 2013-04-20 6 0
library(dplyr)
## extract mean and standard error for loggers and hour of day
data.hourly <- data.hobo %>% group_by(loggerID, hours) %>% summarise(Temp=mean(Temperature),Light=mean(Avg.light),Temp.se=se(Temperature),Light.se=se(Avg.light))
data.hourly <- data.frame(data.hourly)
data.hourly
## loggerID hours Temp Light Temp.se Light.se
## 1 Allan_Laroque 0 16.33226 3.884892e-02 0.3648513 3.884892e-02
## 2 Allan_Laroque 2 15.86632 0.000000e+00 0.3752375 0.000000e+00
## 3 Allan_Laroque 4 15.44694 0.000000e+00 0.3849025 0.000000e+00
## 4 Allan_Laroque 6 15.42670 1.035509e+03 0.3840829 1.158282e+02
## 5 Allan_Laroque 8 17.51994 8.193466e+03 0.3896634 1.046830e+03
## 6 Allan_Laroque 10 19.05345 6.918788e+03 0.3666236 7.941028e+02
## 7 Allan_Laroque 12 19.95085 1.315911e+04 0.3598451 2.255564e+03
## 8 Allan_Laroque 14 20.26105 1.110597e+04 0.3368601 1.783322e+03
## 9 Allan_Laroque 16 19.85099 4.849492e+03 0.3267292 8.117319e+02
## 10 Allan_Laroque 18 18.57063 9.511272e+02 0.3410991 1.095592e+02
## 11 Allan_Laroque 20 17.54351 9.992473e+00 0.3513072 1.811262e+00
## 12 Allan_Laroque 22 16.86679 0.000000e+00 0.3561886 0.000000e+00
## 13 Carrot 0 16.82263 0.000000e+00 0.3622150 0.000000e+00
## 14 Carrot 2 16.20739 0.000000e+00 0.3727668 0.000000e+00
## 15 Carrot 4 15.72073 0.000000e+00 0.3851332 0.000000e+00
## 16 Carrot 6 15.39554 4.072953e+02 0.3877566 4.555910e+01
## 17 Carrot 8 17.65499 1.310946e+04 0.4035867 1.066235e+03
## 18 Carrot 10 21.73332 5.327072e+04 0.4408048 3.547341e+03
## 19 Carrot 12 23.18673 2.713123e+04 0.4373945 2.109609e+03
## 20 Carrot 14 24.80014 6.050654e+04 0.4707862 4.144713e+03
## 21 Carrot 16 24.91188 5.148824e+04 0.4913177 3.335912e+03
## 22 Carrot 18 22.74586 2.203049e+04 0.4549085 1.559317e+03
## 23 Carrot 20 19.01715 2.271777e+03 0.3710476 2.328386e+02
## 24 Carrot 22 17.49219 0.000000e+00 0.3588345 0.000000e+00
## 25 Charles_Sule 0 16.98273 3.884892e-02 0.3451947 3.884892e-02
## 26 Charles_Sule 2 16.38139 0.000000e+00 0.3580559 0.000000e+00
## 27 Charles_Sule 4 15.91030 0.000000e+00 0.3678661 0.000000e+00
## 28 Charles_Sule 6 15.56310 4.616161e+02 0.3711982 5.125079e+01
## 29 Charles_Sule 8 18.76927 2.459781e+04 0.4245105 2.024230e+03
## 30 Charles_Sule 10 23.88400 6.695851e+04 0.4296541 3.850388e+03
## 31 Charles_Sule 12 25.63530 8.205698e+04 0.4626615 4.594056e+03
## 32 Charles_Sule 14 25.11787 6.741514e+04 0.4445177 3.928814e+03
## 33 Charles_Sule 16 23.88458 3.885798e+04 0.4344474 2.359570e+03
## 34 Charles_Sule 18 20.91928 1.122824e+04 0.3769713 8.146276e+02
## 35 Charles_Sule 20 18.61054 1.743957e+03 0.3478528 1.532019e+02
## 36 Charles_Sule 22 17.58751 3.884892e-02 0.3423564 3.884892e-02
## 37 Doro_ground 0 19.19254 0.000000e+00 0.2579197 0.000000e+00
## 38 Doro_ground 2 18.76200 0.000000e+00 0.2717691 0.000000e+00
## 39 Doro_ground 4 18.37085 0.000000e+00 0.2895689 0.000000e+00
## 40 Doro_ground 6 18.03445 1.906283e+02 0.3023740 2.108784e+01
## 41 Doro_ground 8 19.23100 4.393700e+03 0.2500331 3.397543e+02
## 42 Doro_ground 10 24.11629 3.466917e+04 0.3552740 2.782418e+03
## 43 Doro_ground 12 26.68005 5.174972e+04 0.4648171 4.189968e+03
## 44 Doro_ground 14 27.14960 5.277906e+04 0.4784872 4.403371e+03
## 45 Doro_ground 16 26.48112 3.752684e+04 0.4189941 3.105100e+03
## 46 Doro_ground 18 21.98922 3.864414e+03 0.2121463 3.016734e+02
## 47 Doro_ground 20 20.72215 7.474730e+02 0.2229716 6.883104e+01
## 48 Doro_ground 22 19.73769 0.000000e+00 0.2393931 0.000000e+00
## 49 Earth 0 15.43738 0.000000e+00 0.4116454 0.000000e+00
## 50 Earth 2 14.81946 0.000000e+00 0.4223876 0.000000e+00
## 51 Earth 4 14.27596 0.000000e+00 0.4349312 0.000000e+00
## 52 Earth 6 14.00567 3.029344e+02 0.4369798 3.816488e+01
## 53 Earth 8 17.29656 1.246227e+04 0.4485807 1.011235e+03
## 54 Earth 10 22.37986 4.079136e+04 0.4748383 2.735017e+03
## 55 Earth 12 24.27305 4.806232e+04 0.4794273 3.432302e+03
## 56 Earth 14 24.48792 4.491603e+04 0.4293910 3.514977e+03
## 57 Earth 16 24.93144 5.563345e+04 0.4678822 4.189199e+03
## 58 Earth 18 23.24071 3.521375e+04 0.4964829 2.988325e+03
## 59 Earth 20 18.34003 1.821471e+03 0.4027971 1.776731e+02
## 60 Earth 22 16.35201 0.000000e+00 0.4031816 0.000000e+00
## select one logger to plot
Carrot.logger <- subset(data.hourly, loggerID=="Carrot")
par(mfrow=c(1,2)) ## side by side plots
## plot the light radiation on average for each hour of the day during the season
plot(Carrot.logger[,"hours"],Carrot.logger[,"Light"], pch=21, bg="White", ylab="Light (lux)", xlab="hour of the day", ylim=c(0,65000))
error.bar(Carrot.logger[,"hours"],Carrot.logger[,"Light"],Carrot.logger[,"Light.se"])
points(Carrot.logger[,"hours"],Carrot.logger[,"Light"], pch=21, bg="White") ## repeat to cover lines
## plot the temperature on average for each hour of the day during the season
plot(Carrot.logger[,"hours"],Carrot.logger[,"Temp"], pch=21, bg="Black", ylab="Temperature (C°)", xlab="hour of the day", ylim=c(12,28))
error.bar(Carrot.logger[,"hours"],Carrot.logger[,"Temp"],Carrot.logger[,"Temp.se"])
## subset for mid day temperatures and light
mid.day <- subset(data.hobo, hours < 16 & hours > 8) #between 10-14
##summarize mid day values
mid.day.means <- mid.day %>% group_by(loggerID) %>% summarise(Temp=mean(Temperature),Light=mean(Avg.light),Temp.se=se(Temperature),Light.se=se(Avg.light))
mid.day.means <- data.frame(mid.day.means)
mid.day.means
## loggerID Temp Light Temp.se Light.se
## 1 Allan_Laroque 19.75596 10398.78 0.2052735 998.1355
## 2 Carrot 23.23820 46953.31 0.2630108 2008.4484
## 3 Charles_Sule 24.87877 72149.20 0.2583407 2398.7491
## 4 Doro_ground 25.98058 46391.69 0.2557650 2243.3120
## 5 Earth 23.71269 44589.51 0.2683382 1874.4801