【问题标题】:Matplotlib pie charts as scatter plotMatplotlib 饼图作为散点图
【发布时间】:2021-06-05 07:34:44
【问题描述】:

我有一个有趣的问题,我正在尝试使用多个 matplotlib 饼图作为散点图。我已经阅读了this post 关于this matplotlib 教程,并且能够让那些工作。但是,我发现使用内置的饼图函数并在同一轴上绘制许多饼图也能获得相同的结果。

当使用这种替代方法时,我发现在绘制饼图后,轴会丢失它们的标签,并且无论何时平移原始数据仍包含在原始数据的边界内,但饼图是仅包含在图形画布内。

以下代码复制了我遇到的问题。

import matplotlib.pyplot as plt
import pandas as pd
import random

def rand(): #simulate some random data
    return [random.randint(0,100) for _ in range(10)]

def plot_pie(x, ax): 
    ax.pie(x[['a','b','c']], center=(x['lat'],x['lon']), radius=1,colors=['r', 'b', 'g'])

#my data is stored in a similar styled dataframe that I read from a csv and the data is static
sim_data = pd.DataFrame({'a':rand(),'b':rand(),'c':rand(), 'lat':rand(),'lon':rand()})

fig, ax = plt.subplots()
plt.scatter(x=sim_data['lat'], y=sim_data['lon'], s=1000, facecolor='none',edgecolors='r')
y_init = ax.get_ylim()
x_init = ax.get_xlim()

sim_data.apply(lambda x : plot_pie(x,ax), axis=1)
ax.set_ylim(y_init)
ax.set_xlim(x_init)
plt.show()

我重置轴的 x 和 y 限制的原因是我假设饼函数自动将轴的边界设置为最后一个饼图,这是我的工作。

更新

再次阅读文档后,我发现 matplotlib 饼图对象默认设置为不裁剪到任何轴的范围。为了解决它,只需更新该参数似乎对我有用。以下代码是我的问题的解决方案。我还发现,通过绘制每个饼图,我会丢失坐标轴刻度,以解决我必须将 frame 参数传递给饼图的问题。

def plot_pie(x, ax):
    ax.pie(x[['a','b','c']], center=(x['lat'],x['lon']), radius=1,colors=['r', 'b', 'g'], wedgeprops={'clip_on':True}, frame=True)

【问题讨论】:

标签: python pandas matplotlib


【解决方案1】:

按照原始帖子生成的数据。为了清晰起见,我为每个图添加了一个框架。

def plot_pie(x, ax, r=1): 
    # radius for pieplot size on a scatterplot
    ax.pie(x[['a','b','c']], center=(x['lat'],x['lon']), radius=r, colors=['r', 'b', 'g'])

    
fig, axs = plt.subplots(1, 3, figsize=(15, 5))
fig.patch.set_facecolor('white')

# original plot
ax = axs[0]
ax.scatter(x=sim_data['lat'], y=sim_data['lon'], s=1000, facecolor='none', edgecolors='r')
y_init = ax.get_ylim()
x_init = ax.get_xlim()
sim_data.apply(lambda x : plot_pie(x,ax), axis=1)
ax.set_ylim(y_init)
ax.set_xlim(x_init)
ax.set_title('Original')
ax.set_frame_on(True)

# r-beginner's solution
ax = axs[1]
ax.scatter(x=sim_data['lat'], y=sim_data['lon'], s=1000, facecolor='none', edgecolors='r')
y_init = ax.get_ylim()
x_init = ax.get_xlim()
sim_data.apply(lambda x : plot_pie(x,ax), axis=1)
ax.set_ylim([0, y_init[1]*1.1])
ax.set_xlim([0, x_init[1]*1.1])
ax.set_title('r-beginners')
ax.set_frame_on(True)

# my solution
ax = axs[2]
# do not use `s=` for size, it will not work properly when you are scattering pieplots
# because pieplots will be plotted above them
ax.scatter(x=sim_data['lat'], y=sim_data['lon'], s=0)
# git min/max values for the axes
y_init = ax.get_ylim()
x_init = ax.get_xlim()
sim_data.apply(lambda x : plot_pie(x, ax, r=7), axis=1)
# from zero to xlim/ylim with step 10
_ = ax.yaxis.set_ticks(range(0, round(y_init[1])+10, 10))
_ = ax.xaxis.set_ticks(range(0, round(x_init[1])+10, 10))
_ = ax.set_title('My')
ax.set_frame_on(True)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-07-22
    • 2013-06-29
    • 1970-01-01
    • 1970-01-01
    • 2017-06-22
    • 1970-01-01
    相关资源
    最近更新 更多