1

When you export a feature collection (as a CSV) from Google Earth Engine, the geometry information is stored in WKT format under the variable .geo. The general format for each cell in the vector .geo looks something like this:

{""type"":""Point"",""coordinates"":[-16.129853523180806,12.1466390262208]}

If I read in the CSV of the feature collection:

centroidData1 = fread("Tiles/Demo/count_1_plus_rasterdta.csv")

theoretically, we should be able to use .geo to transform centroidData1 into an sf object using the st_as_sf function.

myCRS= "+proj=longlat + datum=WGS84"
  
centroidPoints1= st_as_sf(centroidData1, 
                          wkt=".geo", 
                          na.fail=T, 
                          crs=coordRS)

But when I execute this code, R returns the following error:

OGR: Unsupported geometry type
Error in CPL_sfc_from_wkt(x) : OGR error 

Do I need to reformat the .geo variable first? If yes, how?

2
  • tthat's not wkt, that's json – Elio Diaz Dec 2 '20 at 18:34
  • Ah, I didn't realize that! No wonder it wasn't working! Thank you Elio. – C. Ashley Dec 2 '20 at 20:34
0

Maybe theres a function or parameter in sf to parse the json you are trying to pass to the st_as_sf; since json is a column of your data, it cannot be parsed directly with fromJSON, so you have to parse the column and then put it together with the rest of the data.frame;

I made a csv with this content:

name,quant,geo
a_thing, 1, "{""type"":""Point"",""coordinates"":[-16.129853523180806,12.1466390262208]}"
another_thing, 2, "{""type"":""Point"",""coordinates"":[-16.1299,12.14665]}"

and this is the code that transforms your geo column to sf object:

library(sf)
library(jsonlite)
library(purrr)
library(tidyr)
library(dplyr)
 
df = read.csv("gis.csv")
df %>% mutate(geo = map(geo, ~ fromJSON(.) %>% as.data.frame())) %>% 
  unnest(geo) %>% mutate(coord = rep(c("x","y"),2)) %>%
  pivot_wider(names_from = coord, values_from = coordinates) %>%
  st_as_sf(coords = c("x", "y")) %>% st_set_crs(4326)

prints:

Simple feature collection with 2 features and 3 fields
geometry type:  POINT
dimension:      XY
bbox:           xmin: -16.1299 ymin: 12.14664 xmax: -16.12985 ymax: 12.14665
CRS:            EPSG:4326
# A tibble: 2 x 4
  name          quant type              geometry
* <chr>         <int> <chr>          <POINT [°]>
1 a_thing           1 Point (-16.12985 12.14664)
2 another_thing     2 Point  (-16.1299 12.14665)
6
  • Thank you for the support. I tried executing the provided script but received an error: "Error: Evaluation error: Argument 'txt' must be a JSON string, URL or file." The geo variable in my csv is saved as a factor variable. Any suggestions on how to address this? – C. Ashley Dec 2 '20 at 21:19
  • 1
    Update: I cleaned my data so that the geo variable is a character variable. Now I am getting the error: "Error: Column coord must be length 200 (the number of rows) or one, not 4". This is odd since I currently am working on a subsetted version of the data with 100 rows (not 200). – C. Ashley Dec 2 '20 at 22:11
  • can you do a dput(head(dataframe))? and copy-paste here – Elio Diaz Dec 2 '20 at 22:48
  • ohhhh I see sorry, rep(c("x","y"),2) repeats x y x y; so you should put 100 instead of 2 if your data has 100 rows unnest gives a row for xcoord and a row for ycoord; to make this programmatically use nrow(data.frame) – Elio Diaz Dec 2 '20 at 22:51
  • Thank you! I tried adjusting for the number of rows, but now I am getting a different error: Error in pivot_wider(., names_from = coord, values_from = coordinates) : could not find function "pivot_wider". I am using all the libraries you listed in your original response: might I need one last R package to execute this? Thank you!! – C. Ashley Dec 3 '20 at 2:18
0

Using nothing but fromJSON and base packages you can do this:

> do.call(rbind, Vectorize(fromJSON)(txt=df$geo)[seq(2,nrow(df)*2,by=2)])

to get a two-column matrix of coordinates:

          [,1]     [,2]
[1,] -16.12985 12.14664
[2,] -16.12990 12.14665

In a one-liner:

> dfs = st_as_sf(
     cbind(
       df, 
       do.call(
          rbind, 
            Vectorize(fromJSON)(txt=df$geo)[seq(2,nrow(df)*2,by=2)]
            )
       ),
      coords=c("1","2"))

which you can then add to your data frame and make an sf object.

The only fragility I can see is that it relies on the JSON decoding as two elements, the "type" and the "coordinates", in that order, since it makes a sequence which extracts those elements by numeric index rather than name.

Whatever you do write yourself a function that does this so that when all those dependent packages change and break your code you only have the one place to fix it.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.