在Matplotlib

时间:2018-10-22 11:32:28

标签: python matplotlib rotation logarithm

问题

我正在使用对数标度的数据,并希望将其旋转以适合一条线。我知道模型,但是不确定要插入正确的旋转角度应插入transform_angles的哪个角度。经过一番尝试和错误后,我知道答案是我要求的轴限制在10度左右。

MWE

import matplotlib.pylab as plt
import numpy as np

plt.clf()
plt.yscale('log')
plt.ylim((1e-11, 1e-1))  # Other data is usually plotted and these are the ranges I need. 
plt.xlim((-0.2, 7.2))
x_fit = np.linspace(0.8, 3.2, 1000)
y_ols = (lambda x: np.exp(np.log(2)*(-20.8 + -1.23 * x)))(x_fit)  # I get these numbers from OLS fitting. 
plt.plot(x_fit, y_ols, 'b-', dashes='', label='__nolegend__')
plt.gca().text(np.min(x_fit), 1.2*y_ols[0], r'$O(2^{{ {:.3}x }})$'.format(-1.23), rotation=-10).set_bbox(dict(facecolor='w', alpha=0.7, edgecolor='k', linewidth=0))  # There are several others lines which have been omitted. 

enter image description here

类似的问题(keeps text rotated in data coordinate system after resizing?)仅使用线性轴,matplotlib demos也是如此。

  

图上的注释以回答评论

     
     
      
  • 在我的全部绘图中,我使用具有twinx()功能的双轴(均在对数刻度上)。所有数据都在ax1上绘制,该yscale('log', basey=10)使用log-10刻度(如图所示)。 (我可以更明确地写y_ols ...)。最终,我想要以10为底的轴。
  •   
  • 用于制作np.gradient的模型来自对某些原始数据的回归拟合,要求以2为底。在对数刻度上,可以很容易地恢复任何所需基数中的梯度。
  •   

使用渐变

使用np.arctantransData.transform_angles(np.array((np.mean(np.gradient(np.log10(y_ols), np.mean(np.diff(x_fit)))),)), np.array([np.min(x_fit), 1.2*y_ols[0]]).reshape((1, 2)), radians=True)[0] 混合使用-1.6和一个角度(以弧度为单位)来恢复对数刻度上的梯度很容易,但是我似乎无法恢复出一个接近的数字到10度(0.17弧度)。

0.17

给出1.2*y_ols[0]弧度(大约-90度),而我需要一个更接近echo $TotIncome; 弧度的数字。也许我应该使用其他基准,或者我做错了所有的事(因此而发帖)。

其他-垂直偏移

从代码中可以看出,当使用connection string时,我为锚点添加了垂直偏移。如果解决方案需要考虑到这一点,那就更好了。

2 个答案:

答案 0 :(得分:4)

请注意,我提供了一个通用类来实现此目的,作为对original question的回答。这将在轴限制更改或缩放事件等方面进行自我更新。它还将与对数刻度一起使用。


因此,在下文中,我将仅提供线性刻度和对数刻度之间的比较,以帮助理解使用链接的matplotlib "text_rotation_relative_to_line" example的方法使用对数刻度或线性刻度实际上没有任何区别。

您首先要在数据坐标中计算角度。只需使用numpy.arctan2和前两个数据(或任何其他配对数据)的差作为参数,即可轻松实现。
然后,您使用ax.transData.transform_angles将数据坐标中给定的角度转换为屏幕坐标中的角度。

下面是在线性和对数刻度上相同情况下的示例(从其他答案中获取数据)。

import matplotlib.pyplot as plt
import numpy as np

fig, (ax1, ax2) = plt.subplots(nrows=2, figsize=(6, 4), sharex=True)

ax2.set_yscale('log')
ax2.set(ylim=(1e-11, 1e-1), xlim=(-0.2, 7.2))

x = np.linspace(0.8, 6.2, 100)
y = (lambda x: 10**(( -2 - x)))(x)  

# angle in data coordinates
angle_data = np.rad2deg(np.arctan2(y[1]-y[0], x[1]-x[0]))

# Apply the exact same code to linear and log axes
for ax in (ax1, ax2):

    ax.plot(x, y, 'b-')

    # angle in screen coordinates
    angle_screen = ax.transData.transform_angles(np.array((angle_data,)), 
                                              np.array([x[0], y[0]]).reshape((1, 2)))[0]

    # using `annotate` allows to specify an offset in units of points
    ax.annotate("Text", xy=(x[0],y[0]), xytext=(2,2), textcoords="offset points", 
                rotation_mode='anchor', rotation=angle_screen)

plt.show()

enter image description here

答案 1 :(得分:0)

对于func swapFirstTwo(array: inout [Int]) { if array.count >= 2 { array.swapAt(0, 1) } } typealias Swapper = (inout [Int]) -> () // And I can have a variable = the function let swapThem: Swapper = swapFirstTwo // And it works like this: var array = [1,2,3] print(array) swapThem(&array) print(array) // But I'm allergic to Global functions! // It would be more swifty to have: extension Array where Element == Int { mutating func swapFirstTwo2() { if count >= 2 { swapAt(0, 1) } } } typealias Swapper2 = (inout [Int]) -> () -> () // But when I do this: let swapThemAgain: Swapper2 = Array.swapFirstTwo2 // I get the error: // Partial application of 'mutating' method is not allowed; calling the function has undefined behavior and will be an error in future Swift versions var array2 = [1,2,3] print(array2) array2.swapFirstTwo2() print(array2) // This in fact works but I've tried similar things and sometimes they appear to be unstable. // How can I achieve doing: array2.swapFirstTwo2() without getting the error? 使用哪种轴并不重要。您只需要将其角度调整为textbox属性即可。为了更好地演示它,我将更改您的MWE。我将使用figure函数,并且在对数范围内,它应提供-45度斜率的线性函数。而且,如果您检查网格值,情况就是这样(该功能对每个单位下降了十倍)。但是,由于图形的宽高比变形,因此视角不同(两个单位只有一个正方形),您需要对其进行调整。因此,对于给定的数字,正确的斜率值为-26.259度。在代码中查看y(x)=10^(2-x)的值。

对于adjusted_slope的垂直偏移,您可以选择提供最佳视觉效果的值。

textbox

enter image description here