Plotly:当 2 行相互靠近时如何创建指针
Posted
技术标签:
【中文标题】Plotly:当 2 行相互靠近时如何创建指针【英文标题】:Plotly: How to create a pointer when 2 lines close over each other 【发布时间】:2021-07-29 09:04:27 【问题描述】:如何在两条线的交点处创建一个指针?
【问题讨论】:
你能附上你用来生成这张图片的代码,以及DataFrame或DataFrame的样本吗? 【参考方案1】:您的问题和Plotly: How to find and annotate the intersection point between two lines? 之间的唯一区别似乎是您的案例有多个交叉点。您仍然可以使用相同的approach described here,然后考虑多个交叉点的多个注释:
for x, y in zip(x,y):
fig.add_annotation(x=x, y=y,
text = 'lines intersect at x = ' + str(round(x, 2)) + ' and y = ' + str(round(y, 2)),
font=dict(family="sans serif", size=18, color="black"),
ax=0,
ay=-100,
showarrow=True,
arrowhead=1)
完整代码:
import pandas as pd
import plotly.graph_objects as go
import numpy as np
# import dash
# sample dataframe
df = pd.DataFrame()
df['x'] = np.arange(4) +1
df['y1'] = df['x']**3
df['y2'] = [10+val**2.2 for val in df['x']]
df2 = pd.DataFrame('x':[5,6,7],
'y1':[60, 50, 10],
'y2':[26,20,19])
df = pd.concat([df, df2])
# intersection stuff
def _rect_inter_inner(x1,x2):
n1=x1.shape[0]-1
n2=x2.shape[0]-1
X1=np.c_[x1[:-1],x1[1:]]
X2=np.c_[x2[:-1],x2[1:]]
S1=np.tile(X1.min(axis=1),(n2,1)).T
S2=np.tile(X2.max(axis=1),(n1,1))
S3=np.tile(X1.max(axis=1),(n2,1)).T
S4=np.tile(X2.min(axis=1),(n1,1))
return S1,S2,S3,S4
def _rectangle_intersection_(x1,y1,x2,y2):
S1,S2,S3,S4=_rect_inter_inner(x1,x2)
S5,S6,S7,S8=_rect_inter_inner(y1,y2)
C1=np.less_equal(S1,S2)
C2=np.greater_equal(S3,S4)
C3=np.less_equal(S5,S6)
C4=np.greater_equal(S7,S8)
ii,jj=np.nonzero(C1 & C2 & C3 & C4)
return ii,jj
def intersection(x1,y1,x2,y2):
ii,jj=_rectangle_intersection_(x1,y1,x2,y2)
n=len(ii)
dxy1=np.diff(np.c_[x1,y1],axis=0)
dxy2=np.diff(np.c_[x2,y2],axis=0)
T=np.zeros((4,n))
AA=np.zeros((4,4,n))
AA[0:2,2,:]=-1
AA[2:4,3,:]=-1
AA[0::2,0,:]=dxy1[ii,:].T
AA[1::2,1,:]=dxy2[jj,:].T
BB=np.zeros((4,n))
BB[0,:]=-x1[ii].ravel()
BB[1,:]=-x2[jj].ravel()
BB[2,:]=-y1[ii].ravel()
BB[3,:]=-y2[jj].ravel()
for i in range(n):
try:
T[:,i]=np.linalg.solve(AA[:,:,i],BB[:,i])
except:
T[:,i]=np.NaN
in_range= (T[0,:] >=0) & (T[1,:] >=0) & (T[0,:] <=1) & (T[1,:] <=1)
xy0=T[2:,in_range]
xy0=xy0.T
return xy0[:,0],xy0[:,1]
# plotly figure
x,y=intersection(np.array(df['x'].values.astype('float')),np.array(df['y1'].values.astype('float')),
np.array(df['x'].values.astype('float')),np.array(df['y2'].values.astype('float')))
fig = go.Figure(data=go.Scatter(x=df['x'], y=df['y1'], mode = 'lines'))
fig.add_traces(go.Scatter(x=df['x'], y=df['y2'], mode = 'lines'))
fig.add_traces(go.Scatter(x=x, y=y,
mode = 'markers',
marker=dict(line=dict(color='black', width = 2),
symbol = 'diamond',
size = 14,
color = 'rgba(255, 255, 0, 0.6)'),
name = 'intersect'),
)
for x, y in zip(x,y):
fig.add_annotation(x=x, y=y,
text = 'lines intersect at x = ' + str(round(x, 2)) + ' and y = ' + str(round(y, 2)),
font=dict(family="sans serif", size=18, color="black"),
ax=0,
ay=-100,
showarrow=True,
arrowhead=1)
fig.show()
【讨论】:
以上是关于Plotly:当 2 行相互靠近时如何创建指针的主要内容,如果未能解决你的问题,请参考以下文章