散点图中的饼图切片大小不准确

问题描述 投票:0回答:1

创建了一个以饼图为符号的散点图。这是可行的,但某些切片的大小略有不同,尽管特定饼中所有切片的大小完全相同。

import numpy as np
import matplotlib.pyplot as plt

# Define the function to create the markers
def get_piechart4_markers (fraction_lst):

    cat1_lst = []
    cat2_lst = []
    cat3_lst = []
    cat4_lst = []
    
    for frc in fraction_lst:
        # first define the ratios
        x_lst = np.cos(2 * np.pi * np.linspace(0, frc[0]))
        y_lst = np.sin(2 * np.pi * np.linspace(0, frc[0]))

        cat1_lst += [np.row_stack([[0, 0], np.column_stack([x_lst, y_lst])])]

        # first define the ratios
        x_lst = np.cos(2 * np.pi * np.linspace(frc[0], frc[1]))
        y_lst = np.sin(2 * np.pi * np.linspace(frc[0], frc[1]))

        cat2_lst += [np.row_stack([[0, 0], np.column_stack([x_lst, y_lst])])]
    
        # first define the ratios
        x_lst = np.cos(2 * np.pi * np.linspace(frc[1], frc[2]))
        y_lst = np.sin(2 * np.pi * np.linspace(frc[1], frc[2]))

        cat3_lst += [np.row_stack([[0, 0], np.column_stack([x_lst, y_lst])])]
    
        # first define the ratios
        x_lst = np.cos(2 * np.pi * np.linspace(frc[2], 1))
        y_lst = np.sin(2 * np.pi * np.linspace(frc[2], 1))

        cat4_lst += [np.row_stack([[0, 0], np.column_stack([x_lst, y_lst])])]
        
    return cat1_lst, cat2_lst, cat3_lst, cat4_lst

# Convert to Arrays for plotting
x_arr = np.array([1,2,3,4,5])
y_arr = np.array([1,2,3,4,5])
pie_size_lst = [2000, 4000, 6000, 8000, 10000]
pie_slice_lst = [[0.02, 0.04, 0.08],
                 [0.04, 0.08, 0.16],
                 [0.06, 0.12, 0.24],
                 [0.08, 0.16, 0.32],
                 [0.10, 0.20, 0.40]]

# Get the marker symbols
pie_cat1_lst, pie_cat2_lst, pie_cat3_lst, pie_cat4_lst = get_piechart4_markers( pie_slice_lst )

# Create the plot
fig, ax = plt.subplots(figsize=(10, 10))

# Plot the pie slices
for xp, yp, mr, sm in zip(x_arr, y_arr, pie_cat1_lst, pie_size_lst):
   ax.scatter(xp, yp, marker=mr, s=sm, color='red', alpha=0.9, zorder=10, edgecolors='none')
for xp, yp, mr, sm in zip(x_arr, y_arr, pie_cat2_lst, pie_size_lst):
   ax.scatter(xp, yp, marker=mr, s=sm, color='green', alpha=0.9, zorder=10, edgecolors='none')
for xp, yp, mr, sm in zip(x_arr, y_arr, pie_cat3_lst, pie_size_lst):
   ax.scatter(xp, yp, marker=mr, s=sm, color='blue', alpha=0.9, zorder=10, edgecolors='none')
for xp, yp, mr, sm in zip(x_arr, y_arr, pie_cat4_lst, pie_size_lst):
   ax.scatter(xp, yp, marker=mr, s=sm, color='grey', alpha=0.9, zorder=10, edgecolors='none')

ax.set_xlim(0,6)
ax.set_ylim(0,6)

fig.tight_layout()
image_file_str = r'test_bubble.png'
fig.savefig(image_file_str, facecolor='w', dpi=1000)

我希望所有的馅饼片都有相同的大小。最初我尝试增加到1000dpi,但并没有解决问题。

我从本次讨论中获取的原始代码带有饼图的散点图

结果图

resulting plot

python matplotlib scatter-plot pie-chart
1个回答
0
投票

问题可能是算法使用切片的张角和半径来得出标记的正确“大小(即面积)”。特别是对于较小的张角,当形状变得更加一维时,它选择改变半径。 (丑陋的)解决方法是给切片一个最小的张开角度并让它们重叠。当然,绘图部分的 zorder 现在至关重要。它很丑,但只要我不使用半透明标记,就没人会知道。

import numpy as np
import matplotlib.pyplot as plt

# Define the function to create the markers
def get_piechart4_markers (fraction_lst):

    cat1_lst = []
    cat2_lst = []
    cat3_lst = []
    cat4_lst = []
    
    min_slice_val = 0.25
    
    for frc in fraction_lst:
        
        # Start value is correct, end value based uses minumum fraction cutoff
        start_val = 0
        end_val = np.maximum( min_slice_val, start_val + frc[0])
        
        # first define the ratios
        x_lst = np.cos(2 * np.pi * np.linspace(start_val, end_val))
        y_lst = np.sin(2 * np.pi * np.linspace(start_val, end_val))

        cat1_lst += [np.row_stack([[0, 0], np.column_stack([x_lst, y_lst])])]

        # Start value is correct, end value based uses minumum fraction cutoff
        start_val += frc[0]
        end_val = np.maximum( min_slice_val, start_val + frc[1])

        # first define the ratios
        x_lst = np.cos(2 * np.pi * np.linspace(start_val, end_val))
        y_lst = np.sin(2 * np.pi * np.linspace(start_val, end_val))

        cat2_lst += [np.row_stack([[0, 0], np.column_stack([x_lst, y_lst])])]
    
        # Start value is correct, end value based uses minumum fraction cutoff
        start_val += frc[1]
        end_val = np.maximum( min_slice_val, start_val + frc[2])

        # first define the ratios
        x_lst = np.cos(2 * np.pi * np.linspace(start_val, end_val))
        y_lst = np.sin(2 * np.pi * np.linspace(start_val, end_val))

        cat3_lst += [np.row_stack([[0, 0], np.column_stack([x_lst, y_lst])])]
    
        # Start value is correct, end value based uses minumum fraction cutoff
        start_val += frc[2]
        end_val = 1

        # first define the ratios
        x_lst = np.cos(2 * np.pi * np.linspace(start_val, end_val))
        y_lst = np.sin(2 * np.pi * np.linspace(start_val, end_val))

        cat4_lst += [np.row_stack([[0, 0], np.column_stack([x_lst, y_lst])])]
        
    return cat1_lst, cat2_lst, cat3_lst, cat4_lst

# Convert to Arrays for plotting
x_arr = np.array([1,2,3,4,5])
y_arr = np.array([1,2,3,4,5])
pie_size_lst = [2000, 4000, 6000, 8000, 10000]

pie_slice_lst = [[0.02, 0.04, 0.08],
                 [0.04, 0.08, 0.16],
                 [0.06, 0.12, 0.24],
                 [0.08, 0.16, 0.32],
                 [0.10, 0.20, 0.40]]

# Get the marker symbols
pie_cat1_lst, pie_cat2_lst, pie_cat3_lst, pie_cat4_lst = get_piechart4_markers( pie_slice_lst )

# Create the plot
fig, ax = plt.subplots(figsize=(10, 10))

# Plot the pie slices
for xp, yp, mr, sm in zip(x_arr, y_arr, pie_cat1_lst, pie_size_lst):
   ax.scatter(xp, yp, marker=mr, s=sm, color='red', alpha=1, zorder=21, edgecolors='none')
for xp, yp, mr, sm in zip(x_arr, y_arr, pie_cat2_lst, pie_size_lst):
   ax.scatter(xp, yp, marker=mr, s=sm, color='green', alpha=1, zorder=22, edgecolors='none')
for xp, yp, mr, sm in zip(x_arr, y_arr, pie_cat3_lst, pie_size_lst):
   ax.scatter(xp, yp, marker=mr, s=sm, color='blue', alpha=1, zorder=23, edgecolors='none')
for xp, yp, mr, sm in zip(x_arr, y_arr, pie_cat4_lst, pie_size_lst):
   ax.scatter(xp, yp, marker=mr, s=sm, color='grey', alpha=1, zorder=24, edgecolors='none')

ax.set_xlim(0,6)
ax.set_ylim(0,6)

fig.tight_layout()
image_file_str = r'C:\Users\eikma\NotOnOneDrive\temp\test_bubble.png'
fig.savefig(image_file_str, facecolor='w', dpi=1000)

Plot with the workaround of minimum slice angle

© www.soinside.com 2019 - 2024. All rights reserved.