使用 geopandas 的空间饼图

Spatial pie chart using geopandas

我正在尝试制作如下所示的饼图 -

我正在为此使用 geopandas-

us_states = gpd.read_file("conus_state.shp")
data = gpd.read_file("data_file.shp")

fig, ax = plt.subplots(figsize= (10,10))
us_states.plot(color = "None", ax = ax)
data.plot(column = ["Column1","Column2"], ax= ax, kind = "pie",subplots=True)

这给了我以下错误-

---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
C:\Users\LSRATH~1.STU\AppData\Local\Temp/ipykernel_17992/1047905594.py in <module>
      1 fig, ax = plt.subplots(figsize= (10,10))
      2 us_states.plot(color = "None", ax = ax)
----> 3 diff_env.plot(column = ["WS_MON1","WS_MON2"], ax= ax, kind = "pie")

c:\python38\lib\site-packages\geopandas\plotting.py in __call__(self, *args, **kwargs)
    951         if kind in self._pandas_kinds:
    952             # Access pandas plots
--> 953             return PlotAccessor(data)(kind=kind, **kwargs)
    954         else:
    955             # raise error

c:\python38\lib\site-packages\pandas\plotting\_core.py in __call__(self, *args, **kwargs)
    921             if isinstance(data, ABCDataFrame):
    922                 if y is None and kwargs.get("subplots") is False:
--> 923                     raise ValueError(
    924                         f"{kind} requires either y column or 'subplots=True'"
    925                     )

ValueError: pie requires either y column or 'subplots=True'

即使在指定之后,subplots = True,它也不起作用。

如何使用数据框的 2 列制作饼图?

以下是相关列的前五行-

diff_env[["Column1", "Column2", "geometry"]].head().to_dict()

{'Column1': {0: 2, 1: 0, 2: 0, 3: 1, 4: 12},
 'Column2': {0: 2, 1: 0, 2: 0, 3: 1, 4: 12},
 'geometry': {0: <shapely.geometry.point.Point at 0x2c94e07f190>,
  1: <shapely.geometry.point.Point at 0x2c94e07f130>,
  2: <shapely.geometry.point.Point at 0x2c94e07f0d0>,
  3: <shapely.geometry.point.Point at 0x2c94bb86d30>,
  4: <shapely.geometry.point.Point at 0x2c94e07f310>}}
  • 您没有提供任何可用的示例数据。随机生成了一些
  • 这是受
  • 的启发

示例数据

value0 value1 geometry size
0 5 3 POINT (-105.96116535117056 31.014979334448164) 312
1 2 3 POINT (-79.70609244147155 36.46222924414716) 439
2 4 7 POINT (-68.89518006688962 37.84436728093645) 363
3 7 9 POINT (-118.12344177257525 31.909303946488293) 303
4 2 7 POINT (-102.1001252173913 28.57591221070234) 326
5 3 3 POINT (-96.88772103678929 47.76324025083612) 522
6 5 8 POINT (-112.33188157190635 48.16975143812709) 487
7 7 6 POINT (-95.15025297658862 44.59245298996656) 594
8 3 1 POINT (-100.36265715719063 46.787613401337794) 421
9 2 4 POINT (-81.82966451505015 35.161393444816056) 401

完整代码

import geopandas as gpd
import numpy as np
import shapely
import matplotlib.pyplot as plt

states = (
    gpd.read_file(
        "https://raw.githubusercontent.com/nvkelso/natural-earth-vector/master/geojson/ne_110m_admin_1_states_provinces.geojson"
    )
    .loc[lambda d: d["iso_3166_2"].ne("US-AK"), "geometry"]
    .exterior
)

# geodataframe of points where pies are to be plotted
n = 10
pies = gpd.GeoDataFrame(
    geometry=[
        shapely.geometry.Point(xy)
        for xy in zip(
            np.random.choice(np.linspace(*states.total_bounds[[0, 2]], 300), n),
            np.random.choice(np.linspace(*states.total_bounds[[1, 3]], 300), n),
        )
    ],
    data={f"value{c}": np.random.randint(1, 10, n) for c in range(2)},
    crs=states.crs,
).pipe(lambda d: d.assign(size=np.random.randint(300, 600, n)))

# utility function inspired by 
def draw_pie(dist, xpos, ypos, size, ax):
    # for incremental pie slices
    cumsum = np.cumsum(dist)
    cumsum = cumsum / cumsum[-1]
    pie = [0] + cumsum.tolist()

    colors = ["blue", "red", "yellow"]
    for i, (r1, r2) in enumerate(zip(pie[:-1], pie[1:])):
        angles = np.linspace(2 * np.pi * r1, 2 * np.pi * r2)
        x = [0] + np.cos(angles).tolist()
        y = [0] + np.sin(angles).tolist()

        xy = np.column_stack([x, y])
        ax.scatter([xpos], [ypos], marker=xy, s=size, color=colors[i], alpha=1)

    return ax


fig, ax = plt.subplots()

ax = states.plot(ax=ax, edgecolor="black", linewidth=0.5)
for _, r in pies.iterrows():
    ax = draw_pie([r.value0, r.value1], r.geometry.x, r.geometry.y, r["size"], ax)

输出