Repository: geopandas/geopandas

Issue:
BUG: pd.concat crs warning when geometry column is missing from one of the arguments
@martinfleis thanks for the quick reply, it took me a while but I think I found the problem, it's not directly related I guess but it comes from my use of ``sjoin_nearest`` with saved geometries.

The shortest MWE I could come up with was:

```python
import osmnx as ox
import pandas as pd

area = ox.geocode_to_gdf("Ivry-sur-Seine, France").iloc[0].geometry

landuse = ox.geometries_from_polygon(area, tags={"landuse": "commercial"})

buildings = ox.geometries_from_polygon(area, tags={"building": "retail"})

buildings["savedgeom"] = buildings.geometry

nearest = landuse.to_crs('+proj=cea').sjoin_nearest(buildings.to_crs('+proj=cea'))

nearest["geometry"] = nearest["savedgeom"]
del nearest["savedgeom"]

nearest = nearest.to_crs(landuse.crs)

print(buildings.crs, nearest.crs)

pd.concat([nearest, buildings])
```

_Originally posted by @tfardet in https://github.com/geopandas/geopandas/issues/2606#issuecomment-1325571377_
 
---------------------------------------
I've just moved this to a separate issue so it is easier to track / refer to as it does describe a bug.
A minimal reproducer is
```python
import pandas as pd

import geopandas as gpd
gdf = gpd.read_file(gpd.datasets.get_path("nybb"))
print(gdf.crs)
gdf = gdf.assign(geom=gdf.geometry)
pd.concat([gdf[['geometry']],gdf[['geom', 'geometry']]] )

```


Discussion:

Resolving patch:
diff --git a/geopandas/array.py b/geopandas/array.py
--- a/geopandas/array.py
+++ b/geopandas/array.py
@@ -1394,6 +1394,9 @@ def __contains__(self, item):
 
 
 def _get_common_crs(arr_seq):
+    # mask out all None arrays with no crs (most likely auto generated by pandas
+    # from concat with missing column)
+    arr_seq = [ga for ga in arr_seq if not (ga.isna().all() and ga.crs is None)]
 
     crs_set = {arr.crs for arr in arr_seq}
     crs_not_none = [crs for crs in crs_set if crs is not None]


Test patch:
diff --git a/geopandas/tests/test_merge.py b/geopandas/tests/test_merge.py
--- a/geopandas/tests/test_merge.py
+++ b/geopandas/tests/test_merge.py
@@ -1,3 +1,5 @@
+import warnings
+
 import pandas as pd
 import pytest
 from geopandas.testing import assert_geodataframe_equal
@@ -103,6 +105,39 @@ def test_concat_axis0_crs(self):
                 [self.gdf, self.gdf.set_crs("epsg:4326"), self.gdf.set_crs("epsg:4327")]
             )
 
+    def test_concat_axis0_unaligned_cols(self):
+        # https://github.com/geopandas/geopandas/issues/2679
+        gdf = self.gdf.set_crs("epsg:4326").assign(
+            geom=self.gdf.geometry.set_crs("epsg:4327")
+        )
+        both_geom_cols = gdf[["geom", "geometry"]]
+        single_geom_col = gdf[["geometry"]]
+        with warnings.catch_warnings():
+            warnings.simplefilter("error")
+            pd.concat([both_geom_cols, single_geom_col])
+        # Check order of mismatch doesn't matter
+        with warnings.catch_warnings():
+            warnings.simplefilter("error")
+            pd.concat([single_geom_col, both_geom_cols])
+
+        # Side effect of this fix, explicitly provided all none geoseries
+        # will not be warned for (ideally this would still warn)
+        explicit_all_none_case = gdf[["geometry"]].assign(
+            geom=GeoSeries([None for _ in range(len(gdf))])
+        )
+        with warnings.catch_warnings():
+            warnings.simplefilter("error")
+            pd.concat([both_geom_cols, explicit_all_none_case])
+
+        # Check concat with partially None col is not affected by the special casing
+        # for all None no CRS handling
+        with pytest.warns(
+            UserWarning, match=r"CRS not set for some of the concatenation inputs.*"
+        ):
+            partial_none_case = self.gdf[["geometry"]]
+            partial_none_case.iloc[0] = None
+            pd.concat([single_geom_col, partial_none_case])
+
     def test_concat_axis1(self):
 
         res = pd.concat([self.gdf, self.df], axis=1)