0
# Coordinate Reference Systems
1
2
GeoPandas provides comprehensive support for coordinate reference system (CRS) management and coordinate transformations. This enables working with different spatial reference systems, projections, and datum transformations essential for accurate geospatial analysis.
3
4
## Capabilities
5
6
### CRS Management
7
8
Methods for setting, accessing, and managing coordinate reference systems on GeoDataFrame and GeoSeries objects.
9
10
```python { .api }
11
class GeoDataFrame:
12
@property
13
def crs(self):
14
"""
15
The Coordinate Reference System (CRS) represented as a pyproj.CRS object.
16
17
Returns:
18
- pyproj.CRS or None: The coordinate reference system
19
"""
20
...
21
22
@crs.setter
23
def crs(self, value):
24
"""
25
Set the Coordinate Reference System.
26
27
Parameters:
28
- value: CRS definition (string, dict, EPSG code, or pyproj.CRS)
29
"""
30
...
31
32
def set_crs(self, crs, allow_override=False, inplace=False):
33
"""
34
Set the Coordinate Reference System (CRS).
35
36
Parameters:
37
- crs: CRS definition (string, dict, EPSG code, or pyproj.CRS)
38
- allow_override: Allow overriding existing CRS without warning
39
- inplace: Whether to return a new GeoDataFrame or modify in place
40
41
Returns:
42
- GeoDataFrame or None: New GeoDataFrame or None if inplace=True
43
"""
44
...
45
46
def to_crs(self, crs=None, epsg=None, inplace=False):
47
"""
48
Transform geometries to a new coordinate reference system.
49
50
Parameters:
51
- crs: Target CRS (string, dict, EPSG code, or pyproj.CRS)
52
- epsg: EPSG code for target CRS (alternative to crs parameter)
53
- inplace: Whether to return a new GeoDataFrame or modify in place
54
55
Returns:
56
- GeoDataFrame or None: Transformed GeoDataFrame or None if inplace=True
57
"""
58
...
59
60
def estimate_utm_crs(self, datum_name='WGS 84'):
61
"""
62
Estimate the most appropriate UTM CRS based on geometry bounds.
63
64
Parameters:
65
- datum_name: Name of the datum to use (default: 'WGS 84')
66
67
Returns:
68
- pyproj.CRS: Estimated UTM coordinate reference system
69
"""
70
...
71
72
class GeoSeries:
73
@property
74
def crs(self):
75
"""
76
The Coordinate Reference System (CRS) represented as a pyproj.CRS object.
77
78
Returns:
79
- pyproj.CRS or None: The coordinate reference system
80
"""
81
...
82
83
@crs.setter
84
def crs(self, value):
85
"""
86
Set the Coordinate Reference System.
87
88
Parameters:
89
- value: CRS definition (string, dict, EPSG code, or pyproj.CRS)
90
"""
91
...
92
93
def set_crs(self, crs, allow_override=False, inplace=False):
94
"""
95
Set the Coordinate Reference System (CRS).
96
97
Parameters:
98
- crs: CRS definition (string, dict, EPSG code, or pyproj.CRS)
99
- allow_override: Allow overriding existing CRS without warning
100
- inplace: Whether to return a new GeoSeries or modify in place
101
102
Returns:
103
- GeoSeries or None: New GeoSeries or None if inplace=True
104
"""
105
...
106
107
def to_crs(self, crs=None, epsg=None, inplace=False):
108
"""
109
Transform geometries to a new coordinate reference system.
110
111
Parameters:
112
- crs: Target CRS (string, dict, EPSG code, or pyproj.CRS)
113
- epsg: EPSG code for target CRS (alternative to crs parameter)
114
- inplace: Whether to return a new GeoSeries or modify in place
115
116
Returns:
117
- GeoSeries or None: Transformed GeoSeries or None if inplace=True
118
"""
119
...
120
121
def estimate_utm_crs(self, datum_name='WGS 84'):
122
"""
123
Estimate the most appropriate UTM CRS based on geometry bounds.
124
125
Parameters:
126
- datum_name: Name of the datum to use (default: 'WGS 84')
127
128
Returns:
129
- pyproj.CRS: Estimated UTM coordinate reference system
130
"""
131
...
132
```
133
134
## Usage Examples
135
136
### Setting Coordinate Reference Systems
137
138
```python
139
import geopandas as gpd
140
from shapely.geometry import Point
141
142
# Create GeoDataFrame without CRS
143
gdf = gpd.GeoDataFrame({
144
'city': ['New York', 'London', 'Tokyo'],
145
'geometry': [Point(-74.0, 40.7), Point(-0.1, 51.5), Point(139.7, 35.7)]
146
})
147
148
# Set CRS using different methods
149
gdf = gdf.set_crs('EPSG:4326') # Using EPSG code string
150
gdf = gdf.set_crs(4326) # Using EPSG code integer
151
gdf = gdf.set_crs({'init': 'EPSG:4326'}) # Using dictionary
152
gdf = gdf.set_crs('WGS84') # Using common name
153
154
# Set CRS directly via property
155
gdf.crs = 'EPSG:4326'
156
157
# Check current CRS
158
print(gdf.crs)
159
print(gdf.crs.to_string())
160
print(gdf.crs.to_epsg())
161
```
162
163
### Coordinate Transformations
164
165
```python
166
# Transform to different projections
167
gdf_wgs84 = gpd.read_file('data.shp') # Assume WGS84
168
169
# Transform to Web Mercator
170
gdf_mercator = gdf_wgs84.to_crs('EPSG:3857')
171
172
# Transform to UTM (estimated)
173
utm_crs = gdf_wgs84.estimate_utm_crs()
174
gdf_utm = gdf_wgs84.to_crs(utm_crs)
175
176
# Transform using EPSG parameter
177
gdf_utm = gdf_wgs84.to_crs(epsg=32633) # UTM Zone 33N
178
179
# In-place transformation
180
gdf_wgs84.to_crs('EPSG:3857', inplace=True)
181
```
182
183
### Working with Different CRS Formats
184
185
```python
186
# EPSG codes
187
gdf = gdf.to_crs('EPSG:4326') # WGS84
188
gdf = gdf.to_crs('EPSG:3857') # Web Mercator
189
gdf = gdf.to_crs('EPSG:32633') # UTM Zone 33N
190
191
# PROJ strings
192
gdf = gdf.to_crs('+proj=longlat +datum=WGS84 +no_defs')
193
194
# Well-Known Text (WKT)
195
wkt_crs = '''
196
GEOGCS["WGS 84",
197
DATUM["WGS_1984",
198
SPHEROID["WGS 84",6378137,298.257223563]],
199
PRIMEM["Greenwich",0],
200
UNIT["degree",0.0174532925199433]]
201
'''
202
gdf = gdf.to_crs(wkt_crs)
203
204
# Using pyproj.CRS objects
205
from pyproj import CRS
206
crs = CRS.from_epsg(4326)
207
gdf = gdf.to_crs(crs)
208
```
209
210
### UTM Zone Estimation
211
212
```python
213
# Automatically estimate appropriate UTM zone
214
utm_crs = gdf.estimate_utm_crs()
215
print(f"Estimated UTM CRS: {utm_crs}")
216
217
# Transform to estimated UTM for accurate area/distance calculations
218
gdf_utm = gdf.to_crs(utm_crs)
219
areas = gdf_utm.geometry.area # Now in square meters
220
221
# Estimate with different datum
222
utm_nad83 = gdf.estimate_utm_crs(datum_name='NAD83')
223
gdf_nad83 = gdf.to_crs(utm_nad83)
224
```
225
226
### CRS Validation and Information
227
228
```python
229
# Check if CRS is set
230
if gdf.crs is None:
231
print("No CRS defined")
232
else:
233
print(f"CRS: {gdf.crs}")
234
235
# Get CRS information
236
print(f"EPSG Code: {gdf.crs.to_epsg()}")
237
print(f"Authority: {gdf.crs.to_authority()}")
238
print(f"PROJ String: {gdf.crs.to_proj4()}")
239
print(f"WKT: {gdf.crs.to_wkt()}")
240
241
# Check if CRS is geographic (lat/lon) or projected
242
print(f"Is Geographic: {gdf.crs.is_geographic}")
243
print(f"Is Projected: {gdf.crs.is_projected}")
244
print(f"Units: {gdf.crs.axis_info[0].unit_name}")
245
```
246
247
### Handling CRS Mismatches
248
249
```python
250
# Reading files with different CRS
251
gdf1 = gpd.read_file('file1.shp') # UTM Zone 33N
252
gdf2 = gpd.read_file('file2.shp') # WGS84
253
254
# Ensure same CRS before operations
255
if gdf1.crs != gdf2.crs:
256
gdf2 = gdf2.to_crs(gdf1.crs)
257
258
# Or transform both to common CRS
259
common_crs = 'EPSG:4326'
260
gdf1 = gdf1.to_crs(common_crs)
261
gdf2 = gdf2.to_crs(common_crs)
262
263
# Override existing CRS (use with caution)
264
gdf = gdf.set_crs('EPSG:4326', allow_override=True)
265
```
266
267
### Working with Files and CRS
268
269
```python
270
# CRS is preserved when reading files
271
gdf = gpd.read_file('data.shp')
272
print(f"File CRS: {gdf.crs}")
273
274
# Specify CRS when writing files
275
gdf.to_file('output.shp', crs='EPSG:4326')
276
277
# Transform before writing
278
gdf.to_crs('EPSG:3857').to_file('output_mercator.shp')
279
280
# Read file and immediately transform
281
gdf = gpd.read_file('data.shp').to_crs('EPSG:4326')
282
```
283
284
### Performance Considerations
285
286
```python
287
# For area/distance calculations, use appropriate projected CRS
288
gdf_geographic = gpd.read_file('world.shp') # WGS84
289
290
# Inaccurate - using geographic coordinates
291
areas_bad = gdf_geographic.geometry.area
292
293
# Accurate - using projected coordinates
294
gdf_projected = gdf_geographic.to_crs(gdf_geographic.estimate_utm_crs())
295
areas_good = gdf_projected.geometry.area
296
297
# For global data, consider equal-area projections
298
gdf_mollweide = gdf_geographic.to_crs('+proj=moll +datum=WGS84')
299
areas_global = gdf_mollweide.geometry.area
300
```