如何整理数据在Python中正确绘制圆形折线图
折线图未正确连线的问题解决
问题描述
用户编写Python代码,预期绘制ydata与xdata的圆形关系图,包含带标记的折线图和散点图两个子图,但输出的折线图点未正确连接,无法形成圆形。原代码如下:
import matplotlib.pyplot as plt xdata = [-1.9987069285852805, -1.955030386765729, -1.955030386765729, -1.8259096357678795, -1.8259096357678795, -1.6169878720004491, -1.6169878720004491, -1.3373959790579202, -1.3373959790579202, -0.9993534642926399, -0.9993534642926399, -0.6176344077078071, -0.6176344077078071, -0.20892176376743077, -0.20892176376743077, 0.20892176376743032, 0.20892176376743032, 0.6176344077078065, 0.6176344077078065, 0.999353464292642, 0.999353464292642, 1.3373959790579217, 1.3373959790579217, 1.6169878720004487, 1.6169878720004487, 1.8259096357678786, 1.8259096357678786, 1.9550303867657255, 1.9550303867657255, 1.9987069285852832] ydata = (0.0, -0.038801795445724575, 0.038801795445724575, -0.07590776623879933, 0.07590776623879933, -0.10969620340136318, 0.10969620340136318, -0.13869039009450249, 0.13869039009450249, -0.16162314123018345, 0.16162314123018345, -0.1774921855402276, 0.1774921855402276, -0.18560396964016201, 0.18560396964016201, -0.185603969640162, 0.185603969640162, -0.17749218554022747, 0.17749218554022747, -0.16162314123018337, 0.16162314123018337, -0.13869039009450224, 0.13869039009450224, -0.10969620340136294, 0.10969620340136294, -0.0759077662387991, 0.0759077662387991, -0.038801795445725006, 0.038801795445725006, 0.0) fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(16,6)) fig.suptitle('Plot comparison: line vs scatter'+ 3*'\n') fig.subplots_adjust(wspace=1, hspace=3) fig.supxlabel('x') fig.supylabel('y') ax1.plot(xdata, ydata, 'o-', c='blue') ax1.set_title('Line-point plot', c='blue') for i in range(len(xdata)): ax2.scatter(xdata, ydata, c='orange') ax2.set_title('Scatter plot', c='orange') plt.savefig('line_vs_scatter_plot.png') plt.show()
输出图中,折线图的点在相同x值的正负y之间反复连线,无法形成完整的圆形轮廓。
问题原因
原数据的排列顺序是:按x从左到右,每个x值对应正负两个y值依次排列。而Matplotlib的plot函数是按数据列表的顺序依次连接相邻点,导致相同x的正负y点之间被连线,随后直接跳到下一个x值的点,破坏了圆形的连续路径。
解决方案
可以通过重新整理数据顺序,让点按圆形的顺时针或逆时针路径排列,同时优化散点图的冗余代码。
修改后的代码
import matplotlib.pyplot as plt xdata = [-1.9987069285852805, -1.955030386765729, -1.955030386765729, -1.8259096357678795, -1.8259096357678795, -1.6169878720004491, -1.6169878720004491, -1.3373959790579202, -1.3373959790579202, -0.9993534642926399, -0.9993534642926399, -0.6176344077078071, -0.6176344077078071, -0.20892176376743077, -0.20892176376743077, 0.20892176376743032, 0.20892176376743032, 0.6176344077078065, 0.6176344077078065, 0.999353464292642, 0.999353464292642, 1.3373959790579217, 1.3373959790579217, 1.6169878720004487, 1.6169878720004487, 1.8259096357678786, 1.8259096357678786, 1.9550303867657255, 1.9550303867657255, 1.9987069285852832] ydata = (0.0, -0.038801795445724575, 0.038801795445724575, -0.07590776623879933, 0.07590776623879933, -0.10969620340136318, 0.10969620340136318, -0.13869039009450249, 0.13869039009450249, -0.16162314123018345, 0.16162314123018345, -0.1774921855402276, 0.1774921855402276, -0.18560396964016201, 0.18560396964016201, -0.185603969640162, 0.185603969640162, -0.17749218554022747, 0.17749218554022747, -0.16162314123018337, 0.16162314123018337, -0.13869039009450224, 0.13869039009450224, -0.10969620340136294, 0.10969620340136294, -0.0759077662387991, 0.0759077662387991, -0.038801795445725006, 0.038801795445725006, 0.0) # 重新整理数据:先按x从左到右取负y点,再按x从右到左取正y点,形成顺时针圆形路径 neg_y_points = list(zip(xdata[::2], ydata[::2])) # 提取偶数索引的点(x从左到右,y为负或0) pos_y_points = list(zip(xdata[1::2], ydata[1::2]))[::-1] # 提取奇数索引的点,反转后x从右到左,y为正 # 合并成连续的圆形路径数据 sorted_x = [x for x, y in neg_y_points + pos_y_points] sorted_y = [y for x, y in neg_y_points + pos_y_points] fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(16,6)) fig.suptitle('Plot comparison: line vs scatter' + 3*'\n') fig.subplots_adjust(wspace=1, hspace=3) fig.supxlabel('x') fig.supylabel('y') # 使用整理后的数据绘制折线图 ax1.plot(sorted_x, sorted_y, 'o-', c='blue') ax1.set_title('Line-point plot', c='blue') # 散点图无需循环,直接绘制所有点 ax2.scatter(xdata, ydata, c='orange') ax2.set_title('Scatter plot', c='orange') plt.savefig('line_vs_scatter_plot.png') plt.show()
额外优化方案:生成标准圆形数据
如果不需要使用现有手动整理的x/ydata,也可以通过极坐标转直角坐标的方式生成标准圆形数据,更简洁且不易出错:
import numpy as np import matplotlib.pyplot as plt # 生成圆形数据:极坐标转直角坐标 theta = np.linspace(0, 2*np.pi, 100) # 0到2π的角度,共100个点 radius = 2 # 半径匹配原数据范围 x = radius * np.cos(theta) y = radius * np.sin(theta) fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(16,6)) fig.suptitle('Plot comparison: line vs scatter' + 3*'\n') fig.subplots_adjust(wspace=1, hspace=3) fig.supxlabel('x') fig.supylabel('y') ax1.plot(x, y, 'o-', c='blue') ax1.set_title('Line-point plot (standard circle)', c='blue') ax2.scatter(x, y, c='orange') ax2.set_title('Scatter plot (standard circle)', c='orange') plt.savefig('line_vs_scatter_plot.png') plt.show()
内容的提问来源于stack exchange,提问作者hbaromega
相关产品推荐
相关产品推荐

