Repository: geopandas/geopandas

Issue:
BUG: Ambiguous error raised when there is a column named 'crs'
- [x] I have checked that this issue has not already been reported.

- [x] I have confirmed this bug exists on the latest version of geopandas.

- [ ] (optional) I have confirmed this bug exists on the main branch of geopandas.

---

**Note**: Please read [this guide](https://matthewrocklin.com/blog/work/2018/02/28/minimal-bug-reports) detailing how to provide the necessary information for us to reproduce your bug.

#### Code Sample, a copy-pastable example

```python
# Your code here
feature_coll = [
        {
            "id": "1",
            "type": "Feature",
            "properties":  {"crs": "RD"},
            'geometry': {'type': 'Point', 'coordinates': [5.09223108, 52.03598177]},
            "bbox": (2.0, 1.0, 2.0, 1.0),
        },
    ]
df = gpd.GeoDataFrame.from_features(feature_coll)
```

#### Problem description
If you try to read a feature with a property named `crs`, geopandas raises an error. This is not an issue on geopandas version 0.9.0.

```
---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
/var/folders/q9/bqpyr1wn3cn1wzmkc8bqr5kr0000gn/T/ipykernel_5719/3785671930.py in ?()
     14         },
     15 
     16     ]
     17 
---> 18 df = gpd.GeoDataFrame.from_features(feature_coll)

~/miniconda3/envs/pipe/lib/python3.11/site-packages/geopandas/geodataframe.py in ?(cls, features, crs, columns)
    644             if properties is None:
    645                 properties = {}
    646             row.update(properties)
    647             rows.append(row)
--> 648         return cls(rows, columns=columns, crs=crs)

~/miniconda3/envs/pipe/lib/python3.11/site-packages/geopandas/geodataframe.py in ?(self, data, geometry, crs, *args, **kwargs)
    173                     and not self["geometry"].values.crs == crs
    174                 ):
    175                     raise ValueError(crs_mismatch_error)
    176                 self["geometry"] = _ensure_geometry(self["geometry"].values, crs)
--> 177             except TypeError:
    178                 pass
    179             else:
    180                 geometry = "geometry"
...
   1467             f"The truth value of a {type(self).__name__} is ambiguous. "
   1468             "Use a.empty, a.bool(), a.item(), a.any() or a.all()."
   1469         )

ValueError: The truth value of a Series is ambiguous. Use a.empty, a.bool(), a.item(), a.any() or a.all().
```

#### Expected Output

Either avoid the column named `crs` or raise an error that explains this issue more verbosely.


#### Output of ``geopandas.show_versions()``

```
SYSTEM INFO
-----------
python     : 3.11.3 | packaged by conda-forge | (main, Apr  6 2023, 08:58:31) [Clang 14.0.6 ]
executable : /Users/alexey/miniconda3/envs/pipe/bin/python
machine    : macOS-13.4.1-arm64-arm-64bit

GEOS, GDAL, PROJ INFO
---------------------
GEOS       : 3.11.1
GEOS lib   : None
GDAL       : 3.5.3
GDAL data dir: /Users/alexey/miniconda3/envs/pipe/lib/python3.11/site-packages/fiona/gdal_data
PROJ       : 9.2.0
PROJ data dir: /Users/alexey/miniconda3/envs/pipe/lib/python3.11/site-packages/pyproj/proj_dir/share/proj

PYTHON DEPENDENCIES
-------------------
geopandas  : 0.13.2
numpy      : 1.24.2
pandas     : 2.0.0
pyproj     : 3.5.0
shapely    : 2.0.1
fiona      : 1.9.3
geoalchemy2: None
geopy      : 2.3.0
matplotlib : 3.7.1
mapclassify: 2.5.0
pygeos     : None
pyogrio    : 0.5.1
psycopg2   : None
pyarrow    : None
rtree      : 1.0.1
```

</details>



Discussion:
Hi @alexey-ci, thanks for the report. Based on a quick look it seems this was changed by #2578 when _crs was removed as an attribute.

Resolving patch:
diff --git a/geopandas/geodataframe.py b/geopandas/geodataframe.py
--- a/geopandas/geodataframe.py
+++ b/geopandas/geodataframe.py
@@ -1529,7 +1529,10 @@ def __setitem__(self, key, value):
             if pd.api.types.is_scalar(value) or isinstance(value, BaseGeometry):
                 value = [value] * self.shape[0]
             try:
-                crs = getattr(self, "crs", None)
+                if self._geometry_column_name is not None:
+                    crs = getattr(self, "crs", None)
+                else:  # don't use getattr, because a col "crs" might exist
+                    crs = None
                 value = _ensure_geometry(value, crs=crs)
                 if key == "geometry":
                     self._persist_old_default_geometry_colname()


Test patch:
diff --git a/geopandas/tests/test_geodataframe.py b/geopandas/tests/test_geodataframe.py
--- a/geopandas/tests/test_geodataframe.py
+++ b/geopandas/tests/test_geodataframe.py
@@ -1469,3 +1469,11 @@ def test_geodataframe_crs_nonrepresentable_json(crs):
     ):
         gdf_geojson = json.loads(gdf.to_json())
     assert "crs" not in gdf_geojson
+
+
+def test_geodataframe_crs_colname():
+    # https://github.com/geopandas/geopandas/issues/2942
+    gdf = GeoDataFrame({"crs": [1], "geometry": [Point(1, 1)]})
+    assert gdf.crs is None
+    assert gdf["crs"].iloc[0] == 1
+    assert getattr(gdf, "crs") is None