# help: Problem getting centroids inside lists

6 messages
Open this post in threaded view
|

## help: Problem getting centroids inside lists

 Hi everyone, I have a list of coordinates called "ct" and I want to extract the centroids of each sublist, but it only works when it has only 3 or more points. In ct\$b\$two only has one point; in that case, I would rescue that point as If it were a centroid. This is what I did: library(dplyr) library(geosphere) ct <- list(a = list(one = data.frame(lon = c(-180, -160, -60), lat = c(-20, 5, 0)),                     two = data.frame(lon = c(-18, -16, -6), lat = c(-2, 50, 10))),            b = list(one = data.frame(lon = c(-9, -8, -3), lat = c(-1, 25, 5)),                     two = data.frame(lon = c(-90), lat = c(-1)))) coordinates(ct\$a\$one) <- ~lon+lat coordinates(ct\$a\$two) <- ~lon+lat coordinates(ct\$b\$one) <- ~lon+lat coordinates(ct\$b\$two) <- ~lon+lat s <- 1:length(ct) ctply <- list() for (i in s){  for (j in 1:length(ct[[i]])) {   ctply[[i]][j] <- ifelse(test = lengths(ct[[i]][1]) > 2, yes = sapply(X = ct[[i]][j],     FUN = function(y) geosphere::centroid(slot(y, "coords"))), no = ct[[i]][j] )  } } Thanks in advance Regards, Ariel         [[alternative HTML version deleted]] _______________________________________________ R-sig-Geo mailing list [hidden email] https://stat.ethz.ch/mailman/listinfo/r-sig-geo
Open this post in threaded view
|

## Re: help: Problem getting centroids inside lists

 If all of your data frames had enough points then this should work: myfun1 <- function(le) {   list(one=geosphere::centroid(coordinates(le\$one)),        two=geosphere::centroid(coordinates(le\$two))        ) } lapply(ct, myfun1) To handle the one point case, try the following, which I think works with your example data, but is untested if there just two points. It also assumes the data frames are named 'one' and 'two', and will ignore any others. To handle other names, I think you could replace  \$one  with  [[1]]  and  \$two  with  [[2]]  . myfun <- function(le) {   list(one=if (length(le\$one)>1) geosphere::centroid(coordinates(le\$one)) else coodinates(le\$one),        two=if (length(le\$two)>1) geosphere::centroid(coordinates(le\$two)) else coordinates(le\$two)        ) } lapply(ct, myfun) To see a little bit of what's going on, try   myfun(ct[[1]])   myfun1(ct[[1]])   myfun1(ct[[2]])   myfun(ct[[2]]) I would also verify that the length method for objects of class SpatialPoints does return the number of points, as it appears to: > class(ct\$a\$two) [1] "SpatialPoints" attr(,"package") [1] "sp" > length(ct\$a\$one) [1] 3 > length(ct\$a\$two) [1] 3 > length(ct\$a\$two) [1] 3 > length(ct\$b\$two) [1] 1 -- Don MacQueen Lawrence Livermore National Laboratory 7000 East Ave., L-627 Livermore, CA 94550 925-423-1062 Lab cell 925-724-7509     ﻿On 9/10/18, 10:56 AM, "R-sig-Geo on behalf of Ariel Fuentesdi" <[hidden email] on behalf of [hidden email]> wrote:     Hi everyone,         I have a list of coordinates called "ct" and I want to extract the     centroids of each sublist, but it only works when it has only 3 or more     points. In ct\$b\$two only has one point; in that case, I would rescue that     point as If it were a centroid.         This is what I did:         library(dplyr)     library(geosphere)         ct <- list(a = list(one = data.frame(lon = c(-180, -160, -60), lat = c(-20,     5, 0)),                         two = data.frame(lon = c(-18, -16, -6), lat = c(-2, 50,     10))),                b = list(one = data.frame(lon = c(-9, -8, -3), lat = c(-1, 25,     5)),                         two = data.frame(lon = c(-90), lat = c(-1))))         coordinates(ct\$a\$one) <- ~lon+lat     coordinates(ct\$a\$two) <- ~lon+lat     coordinates(ct\$b\$one) <- ~lon+lat     coordinates(ct\$b\$two) <- ~lon+lat         s <- 1:length(ct)     ctply <- list()     for (i in s){      for (j in 1:length(ct[[i]])) {       ctply[[i]][j] <- ifelse(test = lengths(ct[[i]][1]) > 2, yes = sapply(X =     ct[[i]][j],         FUN = function(y) geosphere::centroid(slot(y, "coords"))), no =     ct[[i]][j] )      }     }         Thanks in advance         Regards,     Ariel         [[alternative HTML version deleted]]         _______________________________________________     R-sig-Geo mailing list     [hidden email]     https://stat.ethz.ch/mailman/listinfo/r-sig-geo    _______________________________________________ R-sig-Geo mailing list [hidden email] https://stat.ethz.ch/mailman/listinfo/r-sig-geo
Open this post in threaded view
|

## Re: help: Problem getting centroids inside lists

 I went to a more general approach, that is: ctply <- lapply(X = s, FUN = function(x) sapply(X = ct[[x]],           FUN = function(y) if(length(y)>1) geosphere::centroid(slot(y, "coords"))           else sp::coordinates(slot(y, "coords")))) But now I want to add the case when they are only two elements. The dataset will be: ct <- list(a = list(one = data.frame(lon = c(-180, -160, -60), lat = c(-20, 5, 0)),                     two = data.frame(lon = c(-18, -16), lat = c(-2, 50))),            b = list(one = data.frame(lon = c(-9, -8, -3), lat = c(-1, 25, 5)),                     two = data.frame(lon = c(-90), lat = c(-1)))) coordinates(ct\$a\$one) <- ~lon+lat coordinates(ct\$a\$two) <- ~lon+lat coordinates(ct\$b\$one) <- ~lon+lat coordinates(ct\$b\$two) <- ~lon+lat And I did the following but it doesn't work: ctply <- lapply(X = s, FUN = function(x) sapply(X = ct[[x]],                                                 FUN = function(y) if(length(y)>2) geosphere::centroid(slot(y, "coords"))                                                 else if (length(y) == 1) sp::coordinates(slot(y, "coords"))                                                 else mean(sp::coordinates(slot(y, "coords"))))) I need the result of each element of the list will be a matrix of two rows per column (named: one, two). How do I fix it? Regards, Ariel 2018-09-10 17:29 GMT-03:00 MacQueen, Don <[hidden email]>: > If all of your data frames had enough points then this should work: > > myfun1 <- function(le) { >   list(one=geosphere::centroid(coordinates(le\$one)), >        two=geosphere::centroid(coordinates(le\$two)) >        ) > } > > lapply(ct, myfun1) > > To handle the one point case, try the following, which I think works with > your example data, but is untested if there just two points. > It also assumes the data frames are named 'one' and 'two', and will ignore > any others. To handle other names, I think you > could replace  \$one  with  [[1]]  and  \$two  with  [[2]]  . > > myfun <- function(le) { >   list(one=if (length(le\$one)>1) geosphere::centroid(coordinates(le\$one)) > else coodinates(le\$one), >        two=if (length(le\$two)>1) geosphere::centroid(coordinates(le\$two)) > else coordinates(le\$two) >        ) > } > > lapply(ct, myfun) > > > To see a little bit of what's going on, try > >   myfun(ct[[1]]) >   myfun1(ct[[1]]) >   myfun1(ct[[2]]) >   myfun(ct[[2]]) > > > > I would also verify that the length method for objects of class > SpatialPoints does return the number of points, as it appears to: > > > class(ct\$a\$two) > [1] "SpatialPoints" > attr(,"package") > [1] "sp" > > > length(ct\$a\$one) > [1] 3 > > length(ct\$a\$two) > [1] 3 > > length(ct\$a\$two) > [1] 3 > > length(ct\$b\$two) > [1] 1 > > -- > Don MacQueen > Lawrence Livermore National Laboratory > 7000 East Ave., L-627 > Livermore, CA 94550 > 925-423-1062 > Lab cell 925-724-7509 > > > > ﻿On 9/10/18, 10:56 AM, "R-sig-Geo on behalf of Ariel Fuentesdi" < > [hidden email] on behalf of [hidden email]> > wrote: > >     Hi everyone, > >     I have a list of coordinates called "ct" and I want to extract the >     centroids of each sublist, but it only works when it has only 3 or more >     points. In ct\$b\$two only has one point; in that case, I would rescue > that >     point as If it were a centroid. > >     This is what I did: > >     library(dplyr) >     library(geosphere) > >     ct <- list(a = list(one = data.frame(lon = c(-180, -160, -60), lat = > c(-20, >     5, 0)), >                         two = data.frame(lon = c(-18, -16, -6), lat = > c(-2, 50, >     10))), >                b = list(one = data.frame(lon = c(-9, -8, -3), lat = c(-1, > 25, >     5)), >                         two = data.frame(lon = c(-90), lat = c(-1)))) > >     coordinates(ct\$a\$one) <- ~lon+lat >     coordinates(ct\$a\$two) <- ~lon+lat >     coordinates(ct\$b\$one) <- ~lon+lat >     coordinates(ct\$b\$two) <- ~lon+lat > >     s <- 1:length(ct) >     ctply <- list() >     for (i in s){ >      for (j in 1:length(ct[[i]])) { >       ctply[[i]][j] <- ifelse(test = lengths(ct[[i]][1]) > 2, yes = > sapply(X = >     ct[[i]][j], >         FUN = function(y) geosphere::centroid(slot(y, "coords"))), no = >     ct[[i]][j] ) >      } >     } > >     Thanks in advance > >     Regards, >     Ariel > >         [[alternative HTML version deleted]] > >     _______________________________________________ >     R-sig-Geo mailing list >     [hidden email] >     https://stat.ethz.ch/mailman/listinfo/r-sig-geo> > >         [[alternative HTML version deleted]] _______________________________________________ R-sig-Geo mailing list [hidden email] https://stat.ethz.ch/mailman/listinfo/r-sig-geo
Open this post in threaded view
|

## Re: help: Problem getting centroids inside lists

 Maybe the following function is what you're looking for? getcentroids <- function(x1) {   getcentroid <- function(x) {     coords <- slot(x, "coords")     numrows <- dim(coords)[1]     ret <- if(numrows == 2) {       matrix(apply(coords,2,mean), nrow=1)     } else {       if(numrows == 1) {         coords       } else {         geosphere::centroid(coords)       }     }     ret   }   r <- lapply(x1, function(x) as.data.frame(getcentroid(x)))   ret <- matrix(unlist(r), ncol=2, byrow=TRUE)   rownames(ret) <- names(r); colnames(ret) <- c("lon", "lat")   ret } Now call it as lapply(ct, getcentroids) HTH, Vijay. On Wed, Sep 12, 2018 at 2:42 PM Ariel Fuentesdi <[hidden email]> wrote: > I went to a more general approach, that is: > > ctply <- lapply(X = s, FUN = function(x) sapply(X = ct[[x]], >           FUN = function(y) if(length(y)>1) geosphere::centroid(slot(y, > "coords")) >           else sp::coordinates(slot(y, "coords")))) > > But now I want to add the case when they are only two elements. The dataset > will be: > > ct <- list(a = list(one = data.frame(lon = c(-180, -160, -60), lat = c(-20, > 5, 0)), >                     two = data.frame(lon = c(-18, -16), lat = c(-2, 50))), >            b = list(one = data.frame(lon = c(-9, -8, -3), lat = c(-1, 25, > 5)), >                     two = data.frame(lon = c(-90), lat = c(-1)))) > coordinates(ct\$a\$one) <- ~lon+lat > coordinates(ct\$a\$two) <- ~lon+lat > coordinates(ct\$b\$one) <- ~lon+lat > coordinates(ct\$b\$two) <- ~lon+lat > > And I did the following but it doesn't work: > > ctply <- lapply(X = s, FUN = function(x) sapply(X = ct[[x]], >                                                 FUN = function(y) > if(length(y)>2) geosphere::centroid(slot(y, "coords")) >                                                 else if (length(y) == 1) > sp::coordinates(slot(y, "coords")) >                                                 else > mean(sp::coordinates(slot(y, "coords"))))) > > I need the result of each element of the list will be a matrix of two rows > per column (named: one, two). How do I fix it? > > Regards, > Ariel > > 2018-09-10 17:29 GMT-03:00 MacQueen, Don <[hidden email]>: > > > If all of your data frames had enough points then this should work: > > > > myfun1 <- function(le) { > >   list(one=geosphere::centroid(coordinates(le\$one)), > >        two=geosphere::centroid(coordinates(le\$two)) > >        ) > > } > > > > lapply(ct, myfun1) > > > > To handle the one point case, try the following, which I think works with > > your example data, but is untested if there just two points. > > It also assumes the data frames are named 'one' and 'two', and will > ignore > > any others. To handle other names, I think you > > could replace  \$one  with  [[1]]  and  \$two  with  [[2]]  . > > > > myfun <- function(le) { > >   list(one=if (length(le\$one)>1) geosphere::centroid(coordinates(le\$one)) > > else coodinates(le\$one), > >        two=if (length(le\$two)>1) geosphere::centroid(coordinates(le\$two)) > > else coordinates(le\$two) > >        ) > > } > > > > lapply(ct, myfun) > > > > > > To see a little bit of what's going on, try > > > >   myfun(ct[[1]]) > >   myfun1(ct[[1]]) > >   myfun1(ct[[2]]) > >   myfun(ct[[2]]) > > > > > > > > I would also verify that the length method for objects of class > > SpatialPoints does return the number of points, as it appears to: > > > > > class(ct\$a\$two) > > [1] "SpatialPoints" > > attr(,"package") > > [1] "sp" > > > > > length(ct\$a\$one) > > [1] 3 > > > length(ct\$a\$two) > > [1] 3 > > > length(ct\$a\$two) > > [1] 3 > > > length(ct\$b\$two) > > [1] 1 > > > > -- > > Don MacQueen > > Lawrence Livermore National Laboratory > > 7000 East Ave., L-627 > > Livermore, CA 94550 > > 925-423-1062 > > Lab cell 925-724-7509 > > > > > > > > ﻿On 9/10/18, 10:56 AM, "R-sig-Geo on behalf of Ariel Fuentesdi" < > > [hidden email] on behalf of [hidden email]> > > wrote: > > > >     Hi everyone, > > > >     I have a list of coordinates called "ct" and I want to extract the > >     centroids of each sublist, but it only works when it has only 3 or > more > >     points. In ct\$b\$two only has one point; in that case, I would rescue > > that > >     point as If it were a centroid. > > > >     This is what I did: > > > >     library(dplyr) > >     library(geosphere) > > > >     ct <- list(a = list(one = data.frame(lon = c(-180, -160, -60), lat = > > c(-20, > >     5, 0)), > >                         two = data.frame(lon = c(-18, -16, -6), lat = > > c(-2, 50, > >     10))), > >                b = list(one = data.frame(lon = c(-9, -8, -3), lat = c(-1, > > 25, > >     5)), > >                         two = data.frame(lon = c(-90), lat = c(-1)))) > > > >     coordinates(ct\$a\$one) <- ~lon+lat > >     coordinates(ct\$a\$two) <- ~lon+lat > >     coordinates(ct\$b\$one) <- ~lon+lat > >     coordinates(ct\$b\$two) <- ~lon+lat > > > >     s <- 1:length(ct) > >     ctply <- list() > >     for (i in s){ > >      for (j in 1:length(ct[[i]])) { > >       ctply[[i]][j] <- ifelse(test = lengths(ct[[i]][1]) > 2, yes = > > sapply(X = > >     ct[[i]][j], > >         FUN = function(y) geosphere::centroid(slot(y, "coords"))), no = > >     ct[[i]][j] ) > >      } > >     } > > > >     Thanks in advance > > > >     Regards, > >     Ariel > > > >         [[alternative HTML version deleted]] > > > >     _______________________________________________ > >     R-sig-Geo mailing list > >     [hidden email] > >     https://stat.ethz.ch/mailman/listinfo/r-sig-geo> > > > > > > >         [[alternative HTML version deleted]] > > _______________________________________________ > R-sig-Geo mailing list > [hidden email] > https://stat.ethz.ch/mailman/listinfo/r-sig-geo> -- Vijay Lulla Assistant Professor, Dept. of Geography, IUPUI 425 University Blvd, CA-207C. Indianapolis, IN-46202 [hidden email] ORCID: https://orcid.org/0000-0002-0823-2522Webpage: http://vijaylulla.com        [[alternative HTML version deleted]] _______________________________________________ R-sig-Geo mailing list [hidden email] https://stat.ethz.ch/mailman/listinfo/r-sig-geo