Git Product home page Git Product logo

geodataframes.jl's Introduction

GeoDataFrames

Stable Dev CI codecov

Simple geographical vector interaction built on top of ArchGDAL. Inspiration from geopandas.

Some basic examples without explanation follow here, for a complete overview, please check the documentation.

Installation

]add GeoDataFrames

Usage

There's no special type here. You just use normal DataFrames with a Vector of ArchGDAL geometries as a column.

Reading

import GeoDataFrames as GDF
df = GDF.read("test_points.shp")
10×2 DataFrame
 Row │ geometry            name
     │ IGeometr           String
─────┼────────────────────────────
   1 │ Geometry: wkbPoint  test
   2 │ Geometry: wkbPoint  test
   3 │ Geometry: wkbPoint  test
   4 │ Geometry: wkbPoint  test
   5 │ Geometry: wkbPoint  test
   6 │ Geometry: wkbPoint  test
   7 │ Geometry: wkbPoint  test
   8 │ Geometry: wkbPoint  test
   9 │ Geometry: wkbPoint  test
  10 │ Geometry: wkbPoint  test

You can also specify the layer index or layer name in opening, useful if there are multiple layers:

GDF.read("test_points.shp", 0)
GDF.read("test_points.shp", "test_points")

Any keywords arguments are passed on to the underlying ArchGDAL read function:

GDF.read("test.csv", options=["GEOM_POSSIBLE_NAMES=point,linestring", "KEEP_GEOM_COLUMNS=NO"])

Writing

using DataFrames

coords = zip(rand(10), rand(10))
df = DataFrame(geometry=createpoint.(coords), name="test");
GDF.write("test_points.shp", df)

You can also set options such as the layer_name, coordinate reference system, the driver and its options:

import GeoFormatTypes as GFT
GDF.write("test_points.shp", df; layer_name="data", crs=GFT.EPSG(4326), driver="FlatGeoBuf", options=Dict("SPATIAL_INDEX"=>"YES"))

Note that any Tables.jl compatible table with GeoInterface.jl compatible geometries can be written by GeoDataFrames. You might want to pass which column(s) contain geometries, or by defining GeoInterface.geometrycolumns on your table. Multiple geometry columns, when enabled by the driver, can be provided in this way.

table = [(; geom=AG.createpoint(1.0, 2.0), name="test")]
GDF.write(tfn, table; geom_columns=(:geom,),)

Operations

The supported operations are the ArchGDAL operations that are exported again to work on Vectors of geometries as well. Hence, if you can apply all the ArchGDAL operations yourself.

df.geom = buffer(df.geom, 10);  # points turn into polygons
df
10×2 DataFrame
 Row │ geometry              name
     │ IGeometr             String
─────┼──────────────────────────────
   1 │ Geometry: wkbPolygon  test
   2 │ Geometry: wkbPolygon  test
   3 │ Geometry: wkbPolygon  test
   4 │ Geometry: wkbPolygon  test
   5 │ Geometry: wkbPolygon  test
   6 │ Geometry: wkbPolygon  test
   7 │ Geometry: wkbPolygon  test
   8 │ Geometry: wkbPolygon  test
   9 │ Geometry: wkbPolygon  test
  10 │ Geometry: wkbPolygon  test

Reprojection

import GeoFormatTypes as GFT
df.geometry = reproject(df.geometry, GFT.EPSG(4326), GFT.EPSG(28992))
10-element Vector{ArchGDAL.IGeometry{ArchGDAL.wkbPolygon}}:
 Geometry: POLYGON ((-472026.042542408 -4406233.59953401,-537 ... 401))
 Geometry: POLYGON ((-417143.506054105 -4395423.99277048,-482 ... 048))
 Geometry: POLYGON ((-450303.142569437 -4301418.89063867,-515 ... 867))
 Geometry: POLYGON ((-434522.645535154 -4351075.81124634,-500 ... 634))
 Geometry: POLYGON ((-443909.665585927 -4412565.43193349,-509 ... 349))
 Geometry: POLYGON ((-438405.666500747 -4299366.23767677,-503 ... 677))
 Geometry: POLYGON ((-400588.951193713 -4365333.532287,-46626 ... 287))
 Geometry: POLYGON ((-409160.489179734 -4388484.98554538,-474 ... 538))
 Geometry: POLYGON ((-453963.150526169 -4408927.89965336,-519 ... 336))
 Geometry: POLYGON ((-498317.413693272 -4321687.31588764,-563 ... 764))

Plotting

using Plots
plot(df.geometry)

image

geodataframes.jl's People

Contributors

dependabot[bot] avatar evetion avatar github-actions[bot] avatar maxfreu avatar rafaqz avatar visr avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar

geodataframes.jl's Issues

Detect empty columns

Now it gives the following error

MethodError: Cannot `convert` an object of type Type{Missing} to an object of type ArchGDAL.OGRFieldType

TagBot trigger issue

This issue is used to trigger TagBot; feel free to unsubscribe.

If you haven't already, you should update your TagBot.yml to include issue comment triggers.
Please see this post on Discourse for instructions and more details.

If you'd like for me to do this for you, comment TagBot fix on this issue.
I'll open a PR within a few hours, please be patient!

Pointer 'hDS' is NULL in 'GDALDatasetH'.

ERROR: GDALError (CE_Failure, code 10):
        Pointer 'hDS' is NULL in 'GDALDatasetH'.

actually means that the file is not found, but we could be nicer about this.

Geometry column not showing the points explicitly in the README example and MERGING issue.

Hi @evetion:
I have run the example commands in the README file from a Jupyter notebook that accepts Julia.
When I run:
df = GDF.read("test_points.shp")
I obtain a similar table to the one in the example but with the following differences:
The geometry is in the first column and the points do not appear explicitly but only says:
Geometry: wkbPoint

What can be the cause of the difference ?

The other questions is if I can use GeoDataFrames to merge a shapefile with a data frame when both
objects have a column in common. I want to preserve all the shapefile geometric structure.

Thank you very much,
Martín

Change some args in `write` to be keyword?

Wondering if it might make it easier on the user to have some of the arguments to write be keywords?

Then the user wouldn't have to specify every argument if they only want to change, e.g., crs or driver.

isempty export

I noticed that this package re-exports isempty from ArchGDAL. In ArchGDAL it is not exported.

It is unfortunate however to export something that is also exported from Base, leading to

WARNING: both GeoDataFrames and Base export "isempty"; uses of it in module Main must be qualified
ERROR: UndefVarError: isempty not defined

Pointer 'hDefn' is NULL in 'OGR_F_Create'

This error gets thrown when I try to use GeoDataFrames.write() with the .gpkg or .shp file formats. I am certain that it is not a problem with the data, as this error occurs even when trying to write a dataframe that has just been read unmodified from a working .gpkg file. Function was previously working, but has broken after I tried to install the Turf.jl package

Friendlier error messages when file not found

This is an upstream problem in ArchGDAL but I'm opening it here (since this package seems to be aimed at making ArchGDAL's weird pointer-based types friendlier to work with). Here's the problem in a nutshell:

julia> gdf = GDF.read("doesnt_exist.gpkg")
ERROR: GDALError (CE_Failure, code 10):
        Pointer 'hDS' is NULL in 'GDALDatasetH'.

Could we have read() check if a file exists before passing it on to ArchGDAL, and throw a friendlier error message if it doesn't exist?

Convenience plotting method for use with GeoMakie?

Is there any interest in an extension package to support plotting GeoDataFrames with GeoMakie?

Not being able to nicely plot GeoDataFrames directly with GeoMakie has been a small pain point of mine.

Below is a tentative working example implementation.
It was written quickly for a specific purpose but could be generalised.

import ArchGDAL as AG
import Dataframes, GeoDataFrames
using GeoMakie

function plot_map(gdf::DataFrame; geom_col=:geometry)
    f = Figure(; size=(600, 900))
    ga = GeoAxis(
        f[1,1];
        dest="+proj=latlong +datum=WGS84",
        xlabel="Longitude",
        ylabel="Latitude",
        xticklabelpad=15,
        yticklabelpad=40,
        xticklabelsize=10,
        yticklabelsize=10,
        aspect=AxisAspect(0.75)
    )

    plottable = GeoMakie.geo2basic(AG.forceto.(gdf[!, geom_col], AG.wkbPolygon))
    poly!(ga, plottable)

    # Need to auto-set limits explicitly, otherwise tick labels don't appear properly (?)
    autolimits!(ga)
    xlims!(ga)
    ylims!(ga)

    display(f)

    return f
end

read layer

Right now GeoDataFrames.read by default returns the first layer. Since many datasets have only one layer, that is very convenient. But perhaps we should not automatically do this if there are more than 1 layers? Otherwise it is very easy for users to miss the fact that they are only seeing part of the data.

function read(fn::AbstractString, layer::Union{Integer,AbstractString}=0)
ds = AG.read(fn)
layer = AG.getlayer(ds, layer)

Can't write a geojson file

Hi I tried to write a .geojson file from a GeoDataFrame and I get a GDAL error.

import GeoDataFrames as GDF
using DataFrames

coords = zip(rand(10), rand(10))
df = DataFrame(geometry=createpoint.(coords), name="test");

GDF.write("test_points.geojson", df)

yields the following error message when trying to write the geojson

ERROR: GDALError (CE_Failure, code 10):
        Pointer 'hDefn' is NULL in 'OGR_F_Create'.

These are the versions I have

⌅ [c9ce4bd3] ArchGDAL v0.9.3
⌃ [62cb38b5] GeoDataFrames v0.3.1

Feature request: Reading from CSV

Reading point data from columns in a csv file is a very common task, and it would be nice to have a shortcut here, something like
GeoDataFrames.open(fn, crs="espg:3006", geom_columns=(...))

Store geometry column names in dataframe metadata

A colleague trying the package was most stuck by the column name having to be specified manually (e.g. :Shape)

If we have the names available in gdal it would be good to propagate them to dataframe metadata so we can retrieve them automatically.

Exported 3D Point Geometeries Get Flattened (3D -> 2D)

When exporting a GeoDataFrame that has 3D point geometries using GeoDataFrame.write(), the exported 3D geometries get flattened to 2D. This appears to be a geometry typing issue.

It can be corrected by altering the "lookup_type" dictionary in io.jl to associate PointTraits with wkbPoint25D geometries instead of wkbPoint geometries like the following:

const lookup_type = Dict{DataType,AG.OGRwkbGeometryType}(
    AG.GeoInterface.PointTrait => AG.wkbPoint25D,
    AG.GeoInterface.MultiPointTrait => AG.wkbMultiPoint,
    AG.GeoInterface.LineStringTrait => AG.wkbLineString,
    AG.GeoInterface.LinearRingTrait => AG.wkbMultiLineString,
    AG.GeoInterface.MultiLineStringTrait => AG.wkbMultiLineString,
    AG.GeoInterface.PolygonTrait => AG.wkbPolygon,
    AG.GeoInterface.MultiPolygonTrait => AG.wkbMultiPolygon,
)

There's probably a more elegant solution using GeoInterface, but this hack is useful if you only ever work in 3D points.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.