Custom Spider chart --> Display curves instead of lines between point on a polar plot in matplotlib

折月煮酒 提交于 2020-01-23 06:41:05

问题


I have measured the positions of different products in different angles positions (6 values in steps of 60 deg. over a complete rotation). Instead of representing my values on a Cartesian graph where 0 and 360 are the same point, I want to use a polar graph.

With matplotlib, I got a spider chart type graph, but I want to avoid straight lines between points and display and extrapolated values between those. I have a solution that is kind of OK, but I was hoping there is a nice "one liner" I could use to have a more realistic representation or a better tangent handling for some points.

Does anyone have an idea to improve my code below ?

# Libraries
import matplotlib.pyplot as plt
import pandas as pd
import numpy as np

# Some data to play with
df = pd.DataFrame({'measure':[10, -5, 15,20,20, 20,15,5,10], 'angle':[0,45,90,135,180, 225, 270, 315,360]})

# The few lines I would like to avoid...
angles = [y/180*np.pi for x in [np.arange(x, x+45,5) for x in df.angle[:-1]] for y in x]
values = [y for x in [np.linspace(x, df.measure[i+1], 10)[:-1] for i, x in enumerate(df.measure[:-1])] for y in x]
angles.append(360/180*np.pi)
values.append(values[0])

# Initialise the spider plot
ax = plt.subplot(polar=True)

# Plot data
ax.plot(df.angle/180*np.pi, df['measure'], linewidth=1, linestyle='solid', label="Spider chart")
ax.plot(angles, values, linewidth=1, linestyle='solid', label='what I want')
ax.legend()

# Fill area
ax.fill(angles, values, 'b', alpha=0.1)

plt.show()

the result is below, I want something similar to the orange line with some kind of spline to avoid sharp corners I currently get


回答1:


I have a solution that is a patchwork of other solutions. It needs to be cleaned and optimized, but it does the job !

Comments and improvements are always welcome, see below

# https://stackoverflow.com/questions/33962717/interpolating-a-closed-curve-using-scipy

from scipy import interpolate

x=df.measure[:-1] * np.cos(df.angle[:-1]/180*np.pi)
y=df.measure[:-1] * np.sin(df.angle[:-1]/180*np.pi)
x = np.r_[x, x[0]]
y = np.r_[y, y[0]]

# fit splines to x=f(u) and y=g(u), treating both as periodic. also note that s=0
# is needed in order to force the spline fit to pass through all the input points.
tck, u = interpolate.splprep([x, y], s=0, per=True)

# evaluate the spline fits for 1000 evenly spaced distance values
xi, yi = interpolate.splev(np.linspace(0, 1, 1000), tck)

def cart2pol(x, y):
    rho = np.sqrt(x**2 + y**2)
    phi = np.arctan2(y, x)
    return(rho, phi)

# Initialise the spider plot
plt.figure(figsize=(12,8))
ax = plt.subplot(polar=True)

# Plot data
ax.plot(df.angle/180*np.pi, df['measure'], linewidth=1, linestyle='solid', label="Spider chart")
ax.plot(angles, values, linewidth=1, linestyle='solid', label='Interval linearisation')
ax.plot(cart2pol(xi, yi)[1], cart2pol(xi, yi)[0], linewidth=1, linestyle='solid', label='Smooth interpolation')
ax.legend()

# Fill area
ax.fill(angles, values, 'b', alpha=0.1)

plt.show()



来源:https://stackoverflow.com/questions/59493724/custom-spider-chart-display-curves-instead-of-lines-between-point-on-a-polar

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!