How to run multiple dataframes in a list through a block of code using for loops in R?

149 Views Asked by At

I have a dataframe full of bird sightings, and I need to take that data and create .KMV files for each known, named bird territory (territory.name). I have a block of code that will take location data and create these .KMV files. By hand this involves creating a separate .CSV file for each of the named territories and running it individually through the block of code to produce the desired .KML files, but I want to automate the process using an R script.

I have made it so that each territory is in a separate dataframe using split(). Examples of these dataframes are below:

structure(list(season = c(" FA15", " FA15", " FA15", " FA15", 
" FA15"), year = c(2015, 2015, 2015, 2015, 2015), territory.name = c("Rocky", 
"Rocky", "Rocky", "Rocky", "Rocky"), plot = structure(c(10L, 
10L, 10L, 10L, 10L), .Label = c("Buena Vista", "Coches Prietos", 
"Coches Prietos ", "Field Station", "Field Station ", "Isthmus", 
"Navy", "Off-plot", "Offplot", "Portazuela", "Sauces", "Scorpion Ranch", 
"test"), class = "factor"), color.band = c("BKUAP", "BKUAP", 
"BKUAP", "BKUAP", "BKUAP"), lat = c(34.0117649920285, 34.0121079795063, 
34.011702965945, 34.0113220084459, 34.0113999601454), lon = c(-119.758454980329, 
-119.758648015559, -119.758594036102, -119.757832037285, -119.757832037285
)), row.names = c(NA, -5L), class = c("tbl_df", "tbl", "data.frame"
))

and

structure(list(season = c(" FA15", " FA15", " FA15", " FA15", 
" FA15"), year = c(2015, 2015, 2015, 2015, 2015), territory.name = c("Hades", 
"Hades", "Hades", "Hades", "Hades"), plot = structure(c(3L, 3L, 
3L, 3L, 3L), .Label = c("Buena Vista", "Coches Prietos", "Coches Prietos ", 
"Field Station", "Field Station ", "Isthmus", "Navy", "Off-plot", 
"Offplot", "Portazuela", "Sauces", "Scorpion Ranch", "test"), class = "factor"), 
    color.band = c("PPOAY", "PPOAY", "PPOAY", "PPOAY", "PPOAY"
    ), lat = c(33.972684033215, 33.9726449735463, 33.9726769924164, 
    33.9730469696224, 33.9725800137967), lon = c(-119.723170017824, 
    -119.723048983142, -119.723543012515, -119.723651977256, 
    -119.723950959742)), row.names = c(NA, -5L), class = c("tbl_df", 
"tbl", "data.frame"))

Ultimately there are 19 different dataframes in this list, one for each named territory. I think I need to use a for loop here, but have never done that before. Here's what I have so far from studying on Stack Overflow and reading documentation:

library(adehabitat)
library(rgdal)

df.list <- split(Fall2015_most, Fall2015_most$territory.name)

for(x in 1:length(df.list)){
  
###### Below is the code chunk for creating .KML files #####
# Remove rows with NA's in the lat and lon columns
x <- x[!is.na(x$lat) & !is.na(x$lon),]

# Ensure longitude is negative so it works in the western hemisphere 
x$lon <- x$lon*-

# Create a copy of the object to make into a SpatialPointsDataFrame
# Only include three columns (territory.name, x, and y coordinates) for estimating home ranges
# Make sure columns are listed  lon and lat
x.sp <- x[, c("territory.name", "lon", "lat")]

# Create a SpatialPointsDataFrame by defining the coordinates and long lat projection
coordinates(x.sp) <- c("lon", "lat")
proj4string(x.sp) <-CRS("+proj=longlat +ellps=WGS84 +datum=WGS84")
str(x.sp)

kernel.ref <- kernelUD(x.sp, h = "href")  # href = the reference bandwidth
image(kernel.ref) # plot
kernel.ref[[1]]@h # The smoothing factor is stored for each animal in the "h" slot
kernel.lscv <- kernelUD(x.sp, h = "LSCV") # Least square cross validation
image(kernel.lscv) # plot

par("mar")
par(mar=c(1,1,1,1))

plotLSCV(kernel.lscv) # Look for a dip

x.kernel.poly <- getverticeshr(kernel.ref, percent = 70) 
print(x.kernel.poly)  # returns the area of each polygon

# Transform the point and MCP objects. 
x.spgeo <- spTransform(x.sp, CRS("+proj=longlat +ellps=WGS84 +datum=WGS84"))
x.bvkernalgeo <- spTransform(x.kernel.poly, CRS("+proj=longlat +ellps=WGS84 +datum=WGS84"))

# Write data to a KML file that can be viewed in Google Earth
writeOGR(x.spgeo, "x.kml", layer="id", driver="KML", verbose=TRUE)
writeOGR(x.bvkernalgeo, "xBVkernel.kml", layer="id", driver="KML", verbose=TRUE)

} # close bracket for x

When I run this I get the error

Error: $ operator is invalid for atomic vectors

in the line

for (x in 1:length(df.list))

How do I get the code to run for each of the dataframes. The filename I would use to run each territory manually through the code has been replaced by x's. My end goal is to successfully run each dataframe in df.list through the code successfully and automatically. Thanks!

0

There are 0 best solutions below