12

I am trying to plot a collection of points onto a graphic of King County, WA.

I can show the graphic with the following code:

fig, ax = plt.subplots(figsize = (15,15))
kings_county.plot(ax=ax)

This gives me the graphic. I then read in the points from the lat/long of a csv I load.

df = pd.read_csv('kc_house_data_train.csv')
crs = {'init': 'epsg:4326'}

And this puts all of the points in a new dataframe

geometry = [Point(x,y) for x,y in zip(df.lat,df.long)]

geo_df = gpd.GeoDataFrame(df, # specifify your dataframe
                          crs = crs, # this is your coordinate system
                          geometry = geometry) # specify the geometry list we created

However, when I do this

fig, ax = plt.subplots(figsize = (40,40))
kings_county.plot(ax=ax, alpha = 0.4, color = 'grey', aspect = 'auto')
geo_df[geo_df.price >= 750000].plot(ax = ax , markersize = 20, color = 'blue',marker = 'o',label = 'pricey')
geo_df[geo_df.price < 750000].plot(ax = ax , markersize = 20, color = 'blue',marker = 'o',label = 'pricey')
plt.legend()

It just returns an error: ValueError: 'box_aspect' and 'fig_aspect' must be positive Not sure why loading the graphic works but the added points makes it break.

Just looking for understanding of this and a fix, if you can. Thanks

gboffi
  • 22,939
  • 8
  • 54
  • 85
Paul
  • 131
  • 2
  • 7
  • Running into this same error now, did you ever find a work around? – kevin.w.johnson Aug 03 '20 at 20:59
  • 2
    Yes, I changed aspect to 1 for both plot entries. Warning stopped and graph was plotted. – Paul Aug 05 '20 at 18:15
  • Running into this problem as well now. How do you change the aspect to 1 for both plot entries? – Vincent Nov 16 '20 at 05:13
  • 1
    FWIW, I set the box aspect using: https://matplotlib.org/api/_as_gen/matplotlib.axes.Axes.set_box_aspect.html?highlight=matplotlib%20axes%20axes%20set_box_aspect#matplotlib.axes.Axes.set_box_aspect which I had to upgrade to matplotlib 3.3 – Vincent Nov 16 '20 at 05:41
  • Note that passing `aspect=1` as a parameter to `.plot()` to fix this is wrong and dangerous. It's merely papering over a data problem by suppressing the symptom. If you've confused lat and lon, your results will simply be wrong. – doctorG Mar 17 '23 at 17:25

3 Answers3

19

I solved this issue simply setting gdf.plot(aspect=1). It didn't happen in previous versions of geopandas, but it suddenly started happening and I figured it was simply this parameter, as it can be read in the error you gave.

Dharman
  • 30,962
  • 25
  • 85
  • 135
Feliu Serra
  • 191
  • 1
  • 4
3

I had this exact problem and found out the Shapely polygon (x,y) coordinates are (longitude, latitude), so I just had to switch the lat/long order in the zip function and everything worked properly. Thanks to this thread for the solution.

Tyler P.
  • 31
  • 2
0

This is a classic case of a mismatch between a stated CRS and the actual geometry. Note the OP rolled their own GeoDataFrame having created their own geometry list and got lat lon transposed. Thus there would be such a mismatch.

Note the documentation for creating a GeoDataFrame that way gives the example

gdf = geopandas.GeoDataFrame(
    df, geometry=geopandas.points_from_xy(df.Longitude, df.Latitude))

and states

We use geopandas points_from_xy() to transform Longitude and Latitude into a list of shapely.Point objects and set it as a geometry while creating the GeoDataFrame. (note that points_from_xy() is an enhanced wrapper for [Point(x, y) for x, y in zip(df.Longitude, df.Latitude)])

Note the transposition of the order of lat/lon in the zip() relative to the OP.

I found this thread having encountered the error after loading a .gpkg in the same python environment as had been happily working before. It's a data problem, not a geopandas version issue. In my case, I checked the data bounds after reading it in and got

wensum_manual.total_bounds
array([607560.35533316, 324060.06511765, 615703.81324167, 327821.37222748])

and then checking the stored CRS, I got

wensum_manual.crs
<Geographic 2D CRS: EPSG:4326>
Name: WGS 84
Axis Info [ellipsoidal]:
- Lat[north]: Geodetic latitude (degree)
- Lon[east]: Geodetic longitude (degree)
Area of Use:
- name: World.
- bounds: (-180.0, -90.0, 180.0, 90.0)
Datum: World Geodetic System 1984 ensemble
- Ellipsoid: WGS 84
- Prime Meridian: Greenwich

Hang on, those bounds don't look like lat/lon! Yes, the aspect=1 flag suppressed the error and allowed the plot to render, but it's not the correct fix. Here I corrected the erroneous CRS:

wensum_manual = wensum_manual.set_crs(epsg=27700, allow_override=True)
doctorG
  • 1,681
  • 1
  • 11
  • 27