Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to convert list of -sf dataframes into single dataframe with geometry per row in R?

Tags:

r

transform

sf

I'm trying to convert the output from the code below, which is a list of sfc dataframes into a dataframe in which the columns contain simple feature collections -one polygon per observation.

Output from reproducible example and expected output below:

# Reproducible example:  
library(tidyverse)  
library(sf)  
library(magrittr)   

# define radius for circle  
radius <- 40
r <- units::set_units(radius, units::as_units("nmile"), mode = "standard") 
%>% 
units::set_units(units::as_units("m"), mode = "standard")  

# Sample data: 
df <- data.frame(var = c("abc", "bcd", "cab", "dba"), 
lon = c(45,47,1, -109), 
lat = c(7, 10, 59, 30))

# Creating simple features with sf:
df <- df %>% st_as_sf(coords = c("lon", "lat"), dim = "XY")

# Applying Coordinate reference system WGS84:
df <- df %>% st_set_crs(4326)

# create function for finding UTM zones
utm_prj4 <- function(x) {
  coords <- cbind(x, st_coordinates(x))
  long <- coords$X
  lat <- coords$Y
  zone <- if(lat >= 56 && lat < 64 && long >= 3 && long < 12){x <- 32} else 
    if(
      lat >= 72 && lat < 84 && long >= 0 && long < 9) {x <- 31} else if(
        lat >= 72 && lat < 84 && long >= 9 && long < 21) {x <- 33} else if(
          lat >= 72 && lat < 84 && long >= 21 && long < 33) {x <- 35} else if(
            lat >= 72 && lat < 84 && long >= 33 && long < 42) {x <- 37} else{
              x <- (floor((long + 180)/6) %% 60) + 1
        }
  prj <- purrr::map2_chr(zone, lat, function(y, z){
    if (z >= 0){
      paste0("+proj=utm +zone=", y, " +datum=WGS84 +units=m +no_defs")
    } else{
      paste0("+proj=utm +zone=", y, " +south", " +datum=WGS84 +units=m 
         +no_defs")
    }})
  prj
}

# creates a list of data.frames, each with different crs
dfs <- map2(1:4, utm_prj4(df), function(x, y){
  st_transform(df[x,], y)
})
df <- map(dfs, ~ st_buffer(., r))

I tried as.data.frame but it doesnt work. I tried data.frame(t(as.data.frame(df)) and it doesn`t work.

The output from the reproducible example is on the left:

The output from the reproducible example is on the left

like image 648
adl Avatar asked Feb 27 '18 16:02

adl


People also ask

Can you convert a list to a DataFrame in R?

To conclude, the easiest way to convert a list to a dataframe in R is to either use the as. data. frame function or the as_tibble function from dplyr.

How do I combine multiple DataFrames in one R?

To join two data frames (datasets) vertically, use the rbind function. The two data frames must have the same variables, but they do not have to be in the same order. If data frameA has variables that data frameB does not, then either: Delete the extra variables in data frameA or.

How do I convert a DataFrame row to a list in R?

We can convert a given data frame to a list by row we use the split() function. The split() function is used to split the data according to our requirement and the arguments given in the split() function are data itself and the other one is seq() function.

How do I convert a DataFrame from a row to a column in R?

Method 1: Using row. row.name() function is used to set and get the name of the DataFrame. Apply the row.name() function to the copy of the DataFrame and a name to the column which contains the name of the column with the help of the $ sign.


1 Answers

You need to make sure your sf objects have the same crs, otherwise you cannot combine their geometries into a single sfc (simple feature column). Once we transform them into longlat for example, we can just rbind them.

df_ll = map(df, ~ st_transform(., 4326))

df_sf = do.call(rbind, df_ll)
## or using Reduce
df_sf = Reduce(rbind, df_ll)
## or using purrr version of reduce
df_sf = reduce(df_ll, rbind)
like image 145
TimSalabim Avatar answered Nov 14 '22 23:11

TimSalabim