Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/354.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何以pi(Python)的倍数设置轴刻度(matplotlib)_Python_Matplotlib_Plot_Axis Labels - Fatal编程技术网

如何以pi(Python)的倍数设置轴刻度(matplotlib)

如何以pi(Python)的倍数设置轴刻度(matplotlib),python,matplotlib,plot,axis-labels,Python,Matplotlib,Plot,Axis Labels,我想用Python绘制一个图,并用pi的倍数显示x范围的刻度 有没有一个好方法可以做到这一点,而不是手动 我正在考虑使用matplotlib,但其他选项也可以 编辑3:EL_DON的解决方案对我来说是这样的: import matplotlib.ticker as tck import matplotlib.pyplot as plt import numpy as np f,ax=plt.subplots(figsize=(20,10)) x=np.linspace(-10*np.pi, 1

我想用Python绘制一个图,并用pi的倍数显示x范围的刻度

有没有一个好方法可以做到这一点,而不是手动

我正在考虑使用matplotlib,但其他选项也可以

编辑3:EL_DON的解决方案对我来说是这样的:

import matplotlib.ticker as tck
import matplotlib.pyplot as plt
import numpy as np

f,ax=plt.subplots(figsize=(20,10))
x=np.linspace(-10*np.pi, 10*np.pi,1000)
y=np.sin(x)

ax.plot(x/np.pi,y)

ax.xaxis.set_major_formatter(tck.FormatStrFormatter('%g $\pi$'))
ax.xaxis.set_major_locator(tck.MultipleLocator(base=1.0))

plt.style.use("ggplot")


plt.show()
给予:

编辑2(在编辑3中解决!):EL_DON的答案似乎不适合我:

import matplotlib.ticker as tck
import matplotlib.pyplot as plt
import numpy as np

f,ax=plt.subplots(figsize=(20,10))
x=np.linspace(-10*np.pi, 10*np.pi)
y=np.sin(x)

ax.plot(x/np.pi,y)

ax.xaxis.set_major_formatter(tck.FormatStrFormatter('%g $\pi$'))
ax.xaxis.set_major_locator(tck.MultipleLocator(base=1.0))

plt.style.use("ggplot")

plt.show()
给我

看起来真的不对

f,ax=plt.subplots(1)
x=linspace(0,3*pi,1001)
y=sin(x)
ax.plot(x/pi,y)
ax.xaxis.set_major_formatter(FormatStrFormatter('%g $\pi$'))
ax.xaxis.set_major_locator(matplotlib.ticker.MultipleLocator(base=1.0))

我使用了以下答案中的信息:

尽管圣人试图做到这一点,但其灵感来源于

编辑:我对其进行了推广,允许您提供分母、单位值和单位的LaTeX标签作为可选参数。如果您觉得有帮助的话,会包含一个类定义

import numpy as np
import matplotlib.pyplot as plt

def multiple_formatter(denominator=2, number=np.pi, latex='\pi'):
    def gcd(a, b):
        while b:
            a, b = b, a%b
        return a
    def _multiple_formatter(x, pos):
        den = denominator
        num = np.int(np.rint(den*x/number))
        com = gcd(num,den)
        (num,den) = (int(num/com),int(den/com))
        if den==1:
            if num==0:
                return r'$0$'
            if num==1:
                return r'$%s$'%latex
            elif num==-1:
                return r'$-%s$'%latex
            else:
                return r'$%s%s$'%(num,latex)
        else:
            if num==1:
                return r'$\frac{%s}{%s}$'%(latex,den)
            elif num==-1:
                return r'$\frac{-%s}{%s}$'%(latex,den)
            else:
                return r'$\frac{%s%s}{%s}$'%(num,latex,den)
    return _multiple_formatter
​
class Multiple:
    def __init__(self, denominator=2, number=np.pi, latex='\pi'):
        self.denominator = denominator
        self.number = number
        self.latex = latex
​
    def locator(self):
        return plt.MultipleLocator(self.number / self.denominator)
​
    def formatter(self):
        return plt.FuncFormatter(multiple_formatter(self.denominator, self.number, self.latex))
这可以非常简单地使用,无需任何参数:

x = np.linspace(-np.pi, 3*np.pi,500)
plt.plot(x, np.cos(x))
plt.title(r'Multiples of $\pi$')
ax = plt.gca()
ax.grid(True)
ax.set_aspect(1.0)
ax.axhline(0, color='black', lw=2)
ax.axvline(0, color='black', lw=2)
ax.xaxis.set_major_locator(plt.MultipleLocator(np.pi / 2))
ax.xaxis.set_minor_locator(plt.MultipleLocator(np.pi / 12))
ax.xaxis.set_major_formatter(plt.FuncFormatter(multiple_formatter()))
plt.show()

或者它可以以更复杂的方式使用:

tau = np.pi*2
den = 60
major = Multiple(den, tau, r'\tau')
minor = Multiple(den*4, tau, r'\tau')
x = np.linspace(-tau/60, tau*8/60,500)
plt.plot(x, np.exp(-x)*np.cos(60*x))
plt.title(r'Multiples of $\tau$')
ax = plt.gca()
ax.grid(True)
ax.axhline(0, color='black', lw=2)
ax.axvline(0, color='black', lw=2)
ax.xaxis.set_major_locator(major.locator())
ax.xaxis.set_minor_locator(minor.locator())
ax.xaxis.set_major_formatter(major.formatter())
plt.show()

如果要避免在plot命令中用x除以pi,可以使用而不是FormatStrFormatter稍微调整:

import numpy as np
from matplotlib import pyplot as plt
from matplotlib.ticker import FuncFormatter, MultipleLocator

fig,ax = plt.subplots()

x = np.linspace(-5*np.pi,5*np.pi,100)
y = np.sin(x)/x
ax.plot(x,y)
#ax.xaxis.set_major_formatter(FormatStrFormatter('%g $\pi$'))
ax.xaxis.set_major_formatter(FuncFormatter(
   lambda val,pos: '{:.0g}$\pi$'.format(val/np.pi) if val !=0 else '0'
))
ax.xaxis.set_major_locator(MultipleLocator(base=np.pi))

plt.show()
给出以下图像:

将numpy作为np导入
将matplotlib.pyplot作为plt导入
x=np.linspace(0,3*np.pi,1001)
plt.ylim(-3,3)
plt.xlim(0,4*np.pi)
平面图(x,np.sin(x))
勾选位置=[0,np.pi,2*np.pi]
标签=['0'、'$\pi$'、'$2\pi$']
plt.xticks(勾选位置、标签)

pi分数的解决方案:

import numpy as np
import matplotlib.pyplot as plt

from matplotlib import rc
rc('text', usetex=True) # Use LaTeX font

import seaborn as sns
sns.set(color_codes=True)
  • 绘制您的函数:
  • 修改栅格的范围,使其与pi值相对应:
  • 更改轴标签:
  • 我创建了一个类似Scott Centoni的答案的格式化程序和定位器实例

    """Show a simple example of using MultiplePi."""
    
    import matplotlib.pyplot as plt
    import numpy as np
    
    from matplot_fmt_pi import MultiplePi
    
    fig = plt.figure(figsize=(4*np.pi, 2.4))
    axes = fig.add_subplot(111)
    x = np.linspace(-2*np.pi, 2*np.pi, 512)
    axes.plot(x, np.sin(x))
    
    axes.grid(True)
    axes.axhline(0, color='black', lw=2)
    axes.axvline(0, color='black', lw=2)
    axes.set_title("MultiplePi formatting")
    
    pi_manager = MultiplePi(2)
    axes.xaxis.set_major_locator(pi_manager.locator())
    axes.xaxis.set_major_formatter(pi_manager.formatter())
    
    plt.tight_layout()
    plt.savefig("./pi_graph.png", dpi=120)
    

    @Zubo如果这回答了你的问题,你应该接受它作为答案answer@scicalculator是的,现在它实际上显示了一些错误,所以我正在研究itOk,所以我尝试了一些轻微的修改,出现了一些奇怪的行为-我不知道这是从哪里来的。在编辑中发布了它。有人有办法不必先将x除以π吗?@EL_don我找到了一种不必先将x除以的方法,并将其作为另一个答案写了出来。由于邻域空间中没有足够的点数,所以没有解决这个问题。请尝试
    x=np.linspace(-10*np.pi,10*np.pi,1001)
    1001应该足够大,看起来很平滑。@EL_DON,是的,谢谢,就是这样!现在有一个更好的答案。我建议将被接受的答案改为@ScottCentoni的答案。我认为在@Zubo中有一个解决方案。虽然,我不知道他们把它作为一个单独的文件,而不是将函数合并到包中。奇怪的另外,被迫使用他们的
    cos
    实现而不是numpy的实现也不太好。如果用户意外地绘制出大量数据,while循环是否会造成麻烦?它可能不止一次地调用tick格式化程序,如果tick是1e16、2e16等,或者是因为它被意外地用在了错误的绘图上,这会阻塞一分钟吗?不,没关系。必须禁用主定位器和次定位器才能转到大x(否则,在到达格式化程序之前,会出现异常,因此可以返回并修复试图在大x范围内使用此定位器的代码)。然后在我的笔记本电脑上执行时间不到100毫秒,甚至到3e16。最后一个刻度为95492965855137200 pi/3.:)如果您尝试在主刻度中进行小增量,则有一个限制。也就是说,将4改为18或其他值,而不是
    ax.xaxis.set\u major\u locator(plt.multiplelotator(np.pi/4))
    。由于
    den=12
    ,它的格式不好。也许可以将
    den
    更改为60,以支持更多的刻度增量选择。(我之所以要这样做,是因为我制作了一个函数,它将主刻度增量和次刻度增量作为参数,而不是仅设置为pi/4和pi/12)是的,这也让我感到困扰,所以我将它变得更一般。现在,您可以选择所需的分母,或者选择pi以外的其他值。
    ax.set_xticks(np.arange(0, 2*np.pi+0.01, np.pi/4))
    
    labels = ['$0$', r'$\pi/4$', r'$\pi/2$', r'$3\pi/4$', r'$\pi$',
              r'$5\pi/4$', r'$3\pi/2$', r'$7\pi/4$', r'$2\pi$']
    ax.set_xticklabels(labels)
    
    """Show a simple example of using MultiplePi."""
    
    import matplotlib.pyplot as plt
    import numpy as np
    
    from matplot_fmt_pi import MultiplePi
    
    fig = plt.figure(figsize=(4*np.pi, 2.4))
    axes = fig.add_subplot(111)
    x = np.linspace(-2*np.pi, 2*np.pi, 512)
    axes.plot(x, np.sin(x))
    
    axes.grid(True)
    axes.axhline(0, color='black', lw=2)
    axes.axvline(0, color='black', lw=2)
    axes.set_title("MultiplePi formatting")
    
    pi_manager = MultiplePi(2)
    axes.xaxis.set_major_locator(pi_manager.locator())
    axes.xaxis.set_major_formatter(pi_manager.formatter())
    
    plt.tight_layout()
    plt.savefig("./pi_graph.png", dpi=120)