# Changing EPSG values from .shp file

**URL:** <https://discourse.julialang.org/t/changing-epsg-values-from-shp-file/122978>\
**Category:** Geo\
**Created:** [November 22, 2024, 9:08pm UTC](https://discourse.julialang.org/t/changing-epsg-values-from-shp-file/122978 "2024-11-22T21:08:47Z")\
**Posts on this page:** 8\
**Page:** 1

<div class="post-metadata">

**Author:** ![ivyc](https://avatars.discourse-cdn.com/v4/letter/i/50afbb/32.png) [@ivyc](https://discourse.julialang.org/u/ivyc)\
**Post date:** [November 22, 2024, 9:08pm UTC](https://discourse.julialang.org/t/changing-epsg-values-from-shp-file/122978/1 "2024-11-22T21:08:47Z")

</div>

I am trying to convert my .shp file from an EPSG value of 26917 to a EPSG value of 4326. These seems to be an issue with my .shp file not having the EPSG built in. I have tried changing the EPSG using the code below but I receive this error: No CRS found in the GeoDataFrame. Setting to EPSG:4326.  
Cannot reproject geometries because no source CRS is defined.  
And when I try to plot the geometries later the EPSG value never changes. Any suggestions or advice would be greatly appreciated.

using ArchGDAL  
using GeoDataFrames

# Load the shapefile into a GeoDataFrame

shapefile\_path = “…\Data & Resources for Ivy\Williford\_10row\_30m\_rectangle.shp\Williford\_10row\_30m\_rectangle.shp”  
geo\_df = GeoDataFrames.read(shapefile\_path)

# Check if the CRS exists in the GeoDataFrame

if in(:crs, names(geo\_df))  
println("Original CRS: ", geo\_df.crs)  
else  
println(“No CRS found in the GeoDataFrame. Setting to EPSG:4326.”)  
# Create a new CRS reference  
crs = ArchGDAL.importEPSG(4326) # Adjust EPSG code as necessary  
# Assign the CRS to the GeoDataFrame  
geo\_df[!, :crs] .= [crs] # Use broadcasting to assign CRS as a vector  
end

# Define the target CRS (e.g., WGS 84)

target\_crs = ArchGDAL.importEPSG(4326) # Change to the desired target CRS if different

# Extract geometries from the GeoDataFrame

geometries = geo\_df.geom

# Reproject the geometries if the source CRS is set

if in(:crs, names(geo\_df))  
source\_crs = geo\_df.crs  
# Reproject the geometries  
reprojected\_geometries = ArchGDAL.reproject(geometries, source\_crs, target\_crs)

```
# Assign the reprojected geometries back to the GeoDataFrame
geo_df.geom .= reprojected_geometries # Use broadcasting to assign

# Output the WKT of the reprojected geometries to verify
println("Reprojected Geometries:")
for geom in geo_df.geom
    wkt_geom = ArchGDAL.toWKT(geom)
    println(wkt_geom)
end

```

else  
println(“Cannot reproject geometries because no source CRS is defined.”)  
end

---

<div class="post-metadata">

**Author:** ![juliohm](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/juliohm/32/215266_2.png) [@juliohm](https://discourse.julialang.org/u/juliohm)\
**Post date:** [November 22, 2024, 9:28pm UTC](https://discourse.julialang.org/t/changing-epsg-values-from-shp-file/122978/2 "2024-11-22T21:28:59Z")

</div>

> [@ivyc](#):
>
> These seems to be an issue with my .shp file not having the EPSG built in.

The .shp file doesn’t store the CRS. You need to find the .proj file in the same directory. If you don’t have one, then you need to ask the author of the file for the CRS.

Also, take a look at

[https://juliaearth.github.io/geospatial-data-science-with-julia/06-projections.html](https://juliaearth.github.io/geospatial-data-science-with-julia/06-projections.html)

---

<div class="post-metadata">

**Author:** ![Raf](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/raf/32/3383_2.png) [@Raf](https://discourse.julialang.org/u/Raf)\
**Post date:** [November 22, 2024, 10:50pm UTC](https://discourse.julialang.org/t/changing-epsg-values-from-shp-file/122978/3 "2024-11-22T22:50:57Z")

</div>

If you know the source EPSG just specify it manually as e.g. `EPSG(1234)`. You may need to do `using GeoFormatTypes` for that to work.

---

<div class="post-metadata">

**Author:** ![alex-s-gardner](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/alex-s-gardner/32/30210_2.png) [@alex-s-gardner](https://discourse.julialang.org/u/alex-s-gardner)\
**Post date:** [November 22, 2024, 11:31pm UTC](https://discourse.julialang.org/t/changing-epsg-values-from-shp-file/122978/4 "2024-11-22T23:31:46Z")

</div>

What about something like this [NOT TESTED]?

```julia
using GeoDataFrames
import GeoDataFrames as GFT
using Proj

path_2_shapefile = "/example/path/my_shapefile.shp"

# assign EPSG code to the shapefile
gdf = GeoDataFrames.read(path_2_shapefile)
GeoDataFrames.write(path_2_shapefile, gdf; crs=GFT.EPSG(26917))

source_crs1 = GFT.EPSG(26917)
target_crs1 = GFT.EPSG(4326)
trans = Proj.Transformation(source_crs1, target_crs1; always_xy=true)

gdf[:, :geometry] = GO.transform.(trans, gdf.geometry)

path_2_shapefile = "/example/path/my_shapefile_4326.shp"
GeoDataFrames.write(path_2_shapefile, gdf; crs=GFT.EPSG(4326))

```

---

<div class="post-metadata">

**Author:** ![Raf](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/raf/32/3383_2.png) [@Raf](https://discourse.julialang.org/u/Raf)\
**Post date:** [November 23, 2024, 1:26am UTC](https://discourse.julialang.org/t/changing-epsg-values-from-shp-file/122978/5 "2024-11-23T01:26:30Z")

</div>

`GO.reproject` might simplify that too, as you don’t need to define the transformation.

(I was trying to stick to ops use of ArchGDAL.jl, but as author of both reproject methods and transform I would use `GO.reproject` now)

Also needs `import GeoFormatTypes as GFT`, small typo there in the package name

---

<div class="post-metadata">

**Author:** ![evetion](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/evetion/32/22679_2.png) [@evetion](https://discourse.julialang.org/u/evetion)\
**Post date:** [November 23, 2024, 6:20pm UTC](https://discourse.julialang.org/t/changing-epsg-values-from-shp-file/122978/6 "2024-11-23T18:20:40Z")

</div>

Hi @ivyc, welcome to the community. May I ask where you got the idea to store the crs as a column in the DataFrame?

The CRS in a (Geo)DataFrame can be stored in its metadata and/or in the stored geometries. It can also be hardcoded during writing (`crs` keyword). I just made a new release of GeoDataFrames (v0.3.11), which enables the following:

```julia
using GeoDataFrames # no other imports needed

gdf = GeoDataFrames.read("test.shp")
crs(gdf) # nothing, because no .prj was found
df = reproject(gdf, EPSG(26917), EPSG(4326))
crs(df) # EPSG{1}((4326,))

GeoDataFrames.write("test_reprojected.shp", df)

```

As pointed out by Júlio, shapefiles requires a separate file for storing their crs. I would suggest to [move away from shapefiles](http://switchfromshapefile.org/), and use something like a [geopackage](https://www.geopackage.org/). Just `GeoDataFrames.write("test.gpkg", df)` would work for that.

Let me know if this works for you, and whether you have any other questions.

---

<div class="post-metadata">

**Author:** ![joa-quim](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/joa-quim/32/227_2.png) [@joa-quim](https://discourse.julialang.org/u/joa-quim)\
**Post date:** [November 24, 2024, 6:00pm UTC](https://discourse.julialang.org/t/changing-epsg-values-from-shp-file/122978/7 "2024-11-24T18:00:34Z")

</div>

To add another option, this how we do that with GMT.jl The test file is a tinny one from the GDAL autotests, renamed to `.shp.zip` to simplify things. But since .zip files (or .shp) are not accepted here I cannot provide that data file

```julia
D = gmtread("poly.shp.zip")
Vector{GMTdataset} with 10 segments
...
PROJ: +proj=tmerc +lat_0=49 +lon_0=-2 +k=0.9996012717 +x_0=400000 +y_0=-100000 +ellps=airy +units=m +no_defs
...

```

Now reproject it to geogs

```julia
xy2lonlat(D, t_srs=4326)
Vector{GMTdataset} with 10 segments
...
PROJ: +proj=longlat +datum=WGS84 +no_defs

20×2 GMTdataset{Float64, 2}
 Row │ lon lat
─────┼──────────────────
   1 │ 162.859 87.2616
   2 │ 162.887 87.2613
   3 │ 162.9 87.2604
...

```

---

<div class="post-metadata">

**Author:** ![ivyc](https://avatars.discourse-cdn.com/v4/letter/i/50afbb/32.png) [@ivyc](https://discourse.julialang.org/u/ivyc)\
**Post date:** [December 3, 2024, 3:42pm UTC](https://discourse.julialang.org/t/changing-epsg-values-from-shp-file/122978/8 "2024-12-03T15:42:00Z")

</div>

Hi, thank you for your response. Honestly I am picking up this project from some other students and I am just trying to use what they had started, so that is the only reason the crs is stored in the DataFrame.
