tjr
tjr

Reputation: 681

Convert to coordinates over a list of data frames

I am trying to convert point values to coordinates using the sp package to perform operations similar to this question. I have a list of data frames (hundreds in the full data set, 2 short ones here).

> dput(df)
list(structure(list(group = c(22, 43, 43, 36, 9, 20, 35, 18, 
32, 2), mean_x_m = c(-2578373.61904762, -2082265, -1853701.875, 
-2615961.89189189, -1538829.07815509, -1753235.6200847, -1690679.5, 
-1694763.64583333, -1700343.15217391, -1416060), mean_y_m = c(3242738.76190476, 
2563892.5, 1945883.125, 3130074.86486486, 1373724.65001039, 1468737.97186933, 
2123413.5, 1442167.01388889, 2144261.73913043, 1352573.33333333
)), .Names = c("group", "mean_x_m", "mean_y_m"), row.names = c(72L, 
140L, 142L, 121L, 27L, 66L, 114L, 60L, 105L, 5L), class = "data.frame"), 
    structure(list(group = c(12, 12, 47, 30, 39, 34, 47, 22, 
    10, 1), mean_x_m = c(-1830635.68663753, -2891058.33333333, 
    -1637448.59886202, -1974773.67400716, -1571853.24324324, 
    -2723090.33333333, -2704594.92760618, -2240863.49122807, 
    -1940748.88253242, -2176724.69924812), mean_y_m = c(2324222.49926225, 
    3261997.5, 2057096.55049787, 2411733.29933653, 1447883.78378379, 
    3406879.26666667, 3291053.77606178, 2788255.49473684, 2176919.6882151, 
    2920168.77443609)), .Names = c("group", "mean_x_m", "mean_y_m"
    ), row.names = c(67L, 68L, 243L, 155L, 202L, 173L, 244L, 
    114L, 61L, 3L), class = "data.frame"))

I can pull one data frame out at a time and convert to a SpatialPointsDataFrame without issue.

df1 = df[[1]]
coordinates(df1) = ~mean_x_m+mean_y_m

My problem is I can't get this to iterate over the entire list using a function, or even get the function to work for a single dataframe.

c = function(f){coordinates(f) = ~mean_x_m+mean_y_m}
df2 = c(df1)
c(df1)
df3 = lapply(df,c)

Would a for loop work better? I'm still learning about working with lists of data frames and matrices so any help on apply or for in this context would be appreciated. Thank you.

Upvotes: 0

Views: 1441

Answers (3)

Robert Hijmans
Robert Hijmans

Reputation: 47036

This is how you can use lapply:

fc <- function(f){coordinates(f) = ~mean_x_m + mean_y_m; f}
lapply(df, fc)

The problem was that your function did not return anything.

To make a single object:

 x <- lapply(1:length(df), function(i) cbind(id=i, df[[i]]))
 x <- do.call(rbind, x)
 coordinates(x) <- ~mean_x_m+mean_y_m

Upvotes: 2

Daniel Bachen
Daniel Bachen

Reputation: 119

If you are working with geographic data I find it is easiest to use Spatial Points and SpatialPointsDataFrame classes to store data. To convert all elements of a list containing dataframes with the same column headings you could adapt this code:

library(sp)
# toy dataset X
X<-list(
x1 = data.frame(group =c("a","b","c"), X = c(-110.1,-110.2,-110), Y = c(44,44.2,44.3)),
x2 = data.frame(group =c("a","b","c"), X = c(-110.1,-110.2,-110), Y = c(44,44.2,44.3)))
# write a function based on the structure of your dfs 
spdf_fxn<-function(df){
SpatialPointsDataFrame(coords= cbind(df$X,df$Y), data= data.frame(group = df$group),
                     proj4string=CRS("+proj=longlat +datum=WGS84"))
}
#apply this function over the list
Out_List<-lapply(X,spdf_fxn) 

Write a function to convert the generic dataframe structure to a SpatialPointsDataframe, with group as the data appended to each point, then apply that function to the list. Note you will have to adapt the column names and use the appropriate proj4string (in this example it is longitude and latitude in WGS 84).

Upvotes: 1

bramtayl
bramtayl

Reputation: 4024

If your dataframes have a consistent structure, it would be better to put them all into one dataframe.

library(dplyr)
library(sp)

result = 
  df %>% 
  bind_rows(.id = "list_number") %>%
  as.data.frame %>%
  `coordinates<-`(~mean_x_m+mean_y_m)

Upvotes: 1

Related Questions