标签归档:matplotlib

matplotlib获取ylim值

问题:matplotlib获取ylim值

matplotlib用来从Python 绘制数据(使用ploterrorbar函数)。我必须绘制一组完全独立的图,然后调整它们的ylim值,以便可以轻松地对其进行视觉比较。

如何ylim从每个图检索值,以便分别取下和上ylim值的最小值和最大值,并调整图以便可以对其进行直观比较?

当然,我可以分析数据并提出自己的自定义ylim值…但是我想用它matplotlib来为我做这些。关于如何轻松(高效)执行此操作的任何建议?

这是我的Python函数,使用绘制matplotlib

import matplotlib.pyplot as plt

def myplotfunction(title, values, errors, plot_file_name):

    # plot errorbars
    indices = range(0, len(values))
    fig = plt.figure()
    plt.errorbar(tuple(indices), tuple(values), tuple(errors), marker='.')

    # axes
    axes = plt.gca()
    axes.set_xlim([-0.5, len(values) - 0.5])
    axes.set_xlabel('My x-axis title')
    axes.set_ylabel('My y-axis title')

    # title
    plt.title(title)

    # save as file
    plt.savefig(plot_file_name)

    # close figure
    plt.close(fig)

I’m using matplotlib to plot data (using plot and errorbar functions) from Python. I have to plot a set of totally separate and independent plots, and then adjust their ylim values so they can be easily visually compared.

How can I retrieve the ylim values from each plot, so that I can take the min and max of the lower and upper ylim values, respectively, and adjust the plots so they can be visually compared?

Of course, I could just analyze the data and come up with my own custom ylim values… but I’d like to use matplotlib to do that for me. Any suggestions on how to easily (and efficiently) do this?

Here’s my Python function that plots using matplotlib:

import matplotlib.pyplot as plt

def myplotfunction(title, values, errors, plot_file_name):

    # plot errorbars
    indices = range(0, len(values))
    fig = plt.figure()
    plt.errorbar(tuple(indices), tuple(values), tuple(errors), marker='.')

    # axes
    axes = plt.gca()
    axes.set_xlim([-0.5, len(values) - 0.5])
    axes.set_xlabel('My x-axis title')
    axes.set_ylabel('My y-axis title')

    # title
    plt.title(title)

    # save as file
    plt.savefig(plot_file_name)

    # close figure
    plt.close(fig)

回答 0

只是使用axes.get_ylim(),它非常类似于set_ylim。从文档

get_ylim()

获取y轴范围[底部,顶部]

Just use axes.get_ylim(), it is very similar to set_ylim. From the docs:

get_ylim()

Get the y-axis range [bottom, top]


回答 1

 ymin, ymax = axes.get_ylim()

如果plt直接使用api,则可以避免完全调用轴:

def myplotfunction(title, values, errors, plot_file_name):

    # plot errorbars
    indices = range(0, len(values))
    fig = plt.figure()
    plt.errorbar(tuple(indices), tuple(values), tuple(errors), marker='.')

    plt.xlim([-0.5, len(values) - 0.5])
    plt.xlabel('My x-axis title')
    plt.ylabel('My y-axis title')

    # title
    plt.title(title)

    # save as file
    plt.savefig(plot_file_name)

   # close figure
    plt.close(fig)
 ymin, ymax = axes.get_ylim()

If you are using the plt api directly, you can avoid calls to the axes altogether:

def myplotfunction(title, values, errors, plot_file_name):

    # plot errorbars
    indices = range(0, len(values))
    fig = plt.figure()
    plt.errorbar(tuple(indices), tuple(values), tuple(errors), marker='.')

    plt.xlim([-0.5, len(values) - 0.5])
    plt.xlabel('My x-axis title')
    plt.ylabel('My y-axis title')

    # title
    plt.title(title)

    # save as file
    plt.savefig(plot_file_name)

   # close figure
    plt.close(fig)

回答 2

利用上面的好答案,并假设您仅按如下方式使用plt

import matplotlib.pyplot as plt

那么您可以使用plt.axis()以下示例中的方法获得所有四个绘图限制。

import matplotlib.pyplot as plt

x = [1, 2, 3, 4, 5, 6, 7, 8]  # fake data
y = [1, 2, 3, 4, 3, 2, 5, 6]

plt.plot(x, y, 'k')

xmin, xmax, ymin, ymax = plt.axis()

s = 'xmin = ' + str(round(xmin, 2)) + ', ' + \
    'xmax = ' + str(xmax) + '\n' + \
    'ymin = ' + str(ymin) + ', ' + \
    'ymax = ' + str(ymax) + ' '

plt.annotate(s, (1, 5))

plt.show()

上面的代码应产生以下输出图。 在此处输入图片说明

Leveraging from the good answers above and assuming you were only using plt as in

import matplotlib.pyplot as plt

then you can get all four plot limits using plt.axis() as in the following example.

import matplotlib.pyplot as plt

x = [1, 2, 3, 4, 5, 6, 7, 8]  # fake data
y = [1, 2, 3, 4, 3, 2, 5, 6]

plt.plot(x, y, 'k')

xmin, xmax, ymin, ymax = plt.axis()

s = 'xmin = ' + str(round(xmin, 2)) + ', ' + \
    'xmax = ' + str(xmax) + '\n' + \
    'ymin = ' + str(ymin) + ', ' + \
    'ymax = ' + str(ymax) + ' '

plt.annotate(s, (1, 5))

plt.show()

The above code should produce the following output plot. enter image description here


在matplotlib中动态更新图

问题:在matplotlib中动态更新图

我正在用Python开发一个应用程序,该应用程序从串行端口收集数据并针对到达时间绘制收集的数据图。数据的到达时间不确定。我希望在收到数据时更新绘图。我搜索了如何执行此操作,发现了两种方法:

  1. 清除绘图,然后重新绘制所有点的绘图。
  2. 通过在特定间隔后对其进行更改来对图进行动画处理。

我不喜欢第一个程序,因为该程序会运行很长时间(例如一天),并且会收集数据,因此重绘该图将非常慢。第二种方法也不可取,因为数据的到达时间不确定,我希望仅在接收到数据时更新绘图。

有没有一种方法可以仅在收到数据后才通过添加更多点来更新图?

I am making an application in Python which collects data from a serial port and plots a graph of the collected data against arrival time. The time of arrival for the data is uncertain. I want the plot to be updated when data is received. I searched on how to do this and found two methods:

  1. Clear the plot and re-draw the plot with all the points again.
  2. Animate the plot by changing it after a particular interval.

I do not prefer the first one as the program runs and collects data for a long time (a day for example), and redrawing the plot will be pretty slow. The second one is also not preferable as time of arrival of data is uncertain and I want the plot to update only when the data is received.

Is there a way in which I can update the plot just by adding more points to it only when the data is received?


回答 0

有没有一种方法可以通过添加更多点来更新图…

matplotlib中有多种动画数据的方式,具体取决于您使用的版本。您看过matplotlib食谱示例吗?另外,请在matplotlib文档中查看更现代的动画示例。最后,动画API定义了一个函数FuncAnimation,该函数可以对一个函数进行实时动画处理。该功能可能只是您用来获取数据的功能。

每种方法基本上都设置了data要绘制的对象的属性,因此不需要清除屏幕或图形。data可以简单地扩展该属性,因此您可以保留先前的点,而只需继续添加到线(或图像或所绘制的任何东西)中。

假设您说数据到达时间不确定,那么最好的选择就是执行以下操作:

import matplotlib.pyplot as plt
import numpy

hl, = plt.plot([], [])

def update_line(hl, new_data):
    hl.set_xdata(numpy.append(hl.get_xdata(), new_data))
    hl.set_ydata(numpy.append(hl.get_ydata(), new_data))
    plt.draw()

然后,当您从串行端口接收数据时,只需调用update_line

Is there a way in which I can update the plot just by adding more point[s] to it…

There are a number of ways of animating data in matplotlib, depending on the version you have. Have you seen the matplotlib cookbook examples? Also, check out the more modern animation examples in the matplotlib documentation. Finally, the animation API defines a function FuncAnimation which animates a function in time. This function could just be the function you use to acquire your data.

Each method basically sets the data property of the object being drawn, so doesn’t require clearing the screen or figure. The data property can simply be extended, so you can keep the previous points and just keep adding to your line (or image or whatever you are drawing).

Given that you say that your data arrival time is uncertain your best bet is probably just to do something like:

import matplotlib.pyplot as plt
import numpy

hl, = plt.plot([], [])

def update_line(hl, new_data):
    hl.set_xdata(numpy.append(hl.get_xdata(), new_data))
    hl.set_ydata(numpy.append(hl.get_ydata(), new_data))
    plt.draw()

Then when you receive data from the serial port just call update_line.


回答 1

为了在不使用FuncAnimation的情况下执行此操作(例如,要在生成图时执行代码的其他部分,或者要同时更新多个图),draw单独调用不会生成图(至少使用qt后端)。

以下对我有用:

import matplotlib.pyplot as plt
plt.ion()
class DynamicUpdate():
    #Suppose we know the x range
    min_x = 0
    max_x = 10

    def on_launch(self):
        #Set up plot
        self.figure, self.ax = plt.subplots()
        self.lines, = self.ax.plot([],[], 'o')
        #Autoscale on unknown axis and known lims on the other
        self.ax.set_autoscaley_on(True)
        self.ax.set_xlim(self.min_x, self.max_x)
        #Other stuff
        self.ax.grid()
        ...

    def on_running(self, xdata, ydata):
        #Update data (with the new _and_ the old points)
        self.lines.set_xdata(xdata)
        self.lines.set_ydata(ydata)
        #Need both of these in order to rescale
        self.ax.relim()
        self.ax.autoscale_view()
        #We need to draw *and* flush
        self.figure.canvas.draw()
        self.figure.canvas.flush_events()

    #Example
    def __call__(self):
        import numpy as np
        import time
        self.on_launch()
        xdata = []
        ydata = []
        for x in np.arange(0,10,0.5):
            xdata.append(x)
            ydata.append(np.exp(-x**2)+10*np.exp(-(x-7)**2))
            self.on_running(xdata, ydata)
            time.sleep(1)
        return xdata, ydata

d = DynamicUpdate()
d()

In order to do this without FuncAnimation (eg you want to execute other parts of the code while the plot is being produced or you want to be updating several plots at the same time), calling draw alone does not produce the plot (at least with the qt backend).

The following works for me:

import matplotlib.pyplot as plt
plt.ion()
class DynamicUpdate():
    #Suppose we know the x range
    min_x = 0
    max_x = 10

    def on_launch(self):
        #Set up plot
        self.figure, self.ax = plt.subplots()
        self.lines, = self.ax.plot([],[], 'o')
        #Autoscale on unknown axis and known lims on the other
        self.ax.set_autoscaley_on(True)
        self.ax.set_xlim(self.min_x, self.max_x)
        #Other stuff
        self.ax.grid()
        ...

    def on_running(self, xdata, ydata):
        #Update data (with the new _and_ the old points)
        self.lines.set_xdata(xdata)
        self.lines.set_ydata(ydata)
        #Need both of these in order to rescale
        self.ax.relim()
        self.ax.autoscale_view()
        #We need to draw *and* flush
        self.figure.canvas.draw()
        self.figure.canvas.flush_events()

    #Example
    def __call__(self):
        import numpy as np
        import time
        self.on_launch()
        xdata = []
        ydata = []
        for x in np.arange(0,10,0.5):
            xdata.append(x)
            ydata.append(np.exp(-x**2)+10*np.exp(-(x-7)**2))
            self.on_running(xdata, ydata)
            time.sleep(1)
        return xdata, ydata

d = DynamicUpdate()
d()

回答 2

这是一种允许在绘制一定数量的点之后删除点的方法:

import matplotlib.pyplot as plt
# generate axes object
ax = plt.axes()

# set limits
plt.xlim(0,10) 
plt.ylim(0,10)

for i in range(10):        
     # add something to axes    
     ax.scatter([i], [i]) 
     ax.plot([i], [i+1], 'rx')

     # draw the plot
     plt.draw() 
     plt.pause(0.01) #is necessary for the plot to update for some reason

     # start removing points if you don't want all shown
     if i>2:
         ax.lines[0].remove()
         ax.collections[0].remove()

Here is a way which allows to remove points after a certain number of points plotted:

import matplotlib.pyplot as plt
# generate axes object
ax = plt.axes()

# set limits
plt.xlim(0,10) 
plt.ylim(0,10)

for i in range(10):        
     # add something to axes    
     ax.scatter([i], [i]) 
     ax.plot([i], [i+1], 'rx')

     # draw the plot
     plt.draw() 
     plt.pause(0.01) #is necessary for the plot to update for some reason

     # start removing points if you don't want all shown
     if i>2:
         ax.lines[0].remove()
         ax.collections[0].remove()

回答 3

我知道我来不及回答这个问题,但是对于您的问题,您可以考虑使用“操纵杆”包装。我设计它用于从串行端口绘制数据流,但它适用于任何流。它还允许交互式文本记录或图像绘图(除了图形绘图外)。无需在单独的线程中执行自己的循环,程序包会照顾它,只需提供您希望的更新频率即可。另外,终端在绘制时仍可用于监视命令。参见http://www.github.com/ceyzeriat/joystick/https://pypi.python.org/pypi/joystick(使用pip install游戏杆进行安装)

只需将np.random.random()替换为您从以下代码中从串行端口读取的实际数据点:

import joystick as jk
import numpy as np
import time

class test(jk.Joystick):
    # initialize the infinite loop decorator
    _infinite_loop = jk.deco_infinite_loop()

    def _init(self, *args, **kwargs):
        """
        Function called at initialization, see the doc
        """
        self._t0 = time.time()  # initialize time
        self.xdata = np.array([self._t0])  # time x-axis
        self.ydata = np.array([0.0])  # fake data y-axis
        # create a graph frame
        self.mygraph = self.add_frame(jk.Graph(name="test", size=(500, 500), pos=(50, 50), fmt="go-", xnpts=10000, xnptsmax=10000, xylim=(None, None, 0, 1)))

    @_infinite_loop(wait_time=0.2)
    def _generate_data(self):  # function looped every 0.2 second to read or produce data
        """
        Loop starting with the simulation start, getting data and
    pushing it to the graph every 0.2 seconds
        """
        # concatenate data on the time x-axis
        self.xdata = jk.core.add_datapoint(self.xdata, time.time(), xnptsmax=self.mygraph.xnptsmax)
        # concatenate data on the fake data y-axis
        self.ydata = jk.core.add_datapoint(self.ydata, np.random.random(), xnptsmax=self.mygraph.xnptsmax)
        self.mygraph.set_xydata(t, self.ydata)

t = test()
t.start()
t.stop()

I know I’m late to answer this question, but for your issue you could look into the “joystick” package. I designed it for plotting a stream of data from the serial port, but it works for any stream. It also allows for interactive text logging or image plotting (in addition to graph plotting). No need to do your own loops in a separate thread, the package takes care of it, just give the update frequency you wish. Plus the terminal remains available for monitoring commands while plotting. See http://www.github.com/ceyzeriat/joystick/ or https://pypi.python.org/pypi/joystick (use pip install joystick to install)

Just replace np.random.random() by your real data point read from the serial port in the code below:

import joystick as jk
import numpy as np
import time

class test(jk.Joystick):
    # initialize the infinite loop decorator
    _infinite_loop = jk.deco_infinite_loop()

    def _init(self, *args, **kwargs):
        """
        Function called at initialization, see the doc
        """
        self._t0 = time.time()  # initialize time
        self.xdata = np.array([self._t0])  # time x-axis
        self.ydata = np.array([0.0])  # fake data y-axis
        # create a graph frame
        self.mygraph = self.add_frame(jk.Graph(name="test", size=(500, 500), pos=(50, 50), fmt="go-", xnpts=10000, xnptsmax=10000, xylim=(None, None, 0, 1)))

    @_infinite_loop(wait_time=0.2)
    def _generate_data(self):  # function looped every 0.2 second to read or produce data
        """
        Loop starting with the simulation start, getting data and
    pushing it to the graph every 0.2 seconds
        """
        # concatenate data on the time x-axis
        self.xdata = jk.core.add_datapoint(self.xdata, time.time(), xnptsmax=self.mygraph.xnptsmax)
        # concatenate data on the fake data y-axis
        self.ydata = jk.core.add_datapoint(self.ydata, np.random.random(), xnptsmax=self.mygraph.xnptsmax)
        self.mygraph.set_xydata(t, self.ydata)

t = test()
t.start()
t.stop()

将y轴格式化为百分比

问题:将y轴格式化为百分比

我有一个用熊猫创建的现有情节,如下所示:

df['myvar'].plot(kind='bar')

y轴的格式为float,我想将y轴更改为百分比。我发现的所有解决方案都使用ax.xyz语法,并且只能将代码放置在创建绘图的上方行下方(我无法在上面的行中添加ax = ax。)

如何在不更改上面的行的情况下将y轴格式化为百分比?

这是我找到的解决方案,但需要重新定义图

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

data = [8,12,15,17,18,18.5]
perc = np.linspace(0,100,len(data))

fig = plt.figure(1, (7,4))
ax = fig.add_subplot(1,1,1)

ax.plot(perc, data)

fmt = '%.0f%%' # Format you want the ticks, e.g. '40%'
xticks = mtick.FormatStrFormatter(fmt)
ax.xaxis.set_major_formatter(xticks)

plt.show()

链接到上述解决方案:Pyplot:在x轴上使用百分比

I have an existing plot that was created with pandas like this:

df['myvar'].plot(kind='bar')

The y axis is format as float and I want to change the y axis to percentages. All of the solutions I found use ax.xyz syntax and I can only place code below the line above that creates the plot (I cannot add ax=ax to the line above.)

How can I format the y axis as percentages without changing the line above?

Here is the solution I found but requires that I redefine the plot:

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

data = [8,12,15,17,18,18.5]
perc = np.linspace(0,100,len(data))

fig = plt.figure(1, (7,4))
ax = fig.add_subplot(1,1,1)

ax.plot(perc, data)

fmt = '%.0f%%' # Format you want the ticks, e.g. '40%'
xticks = mtick.FormatStrFormatter(fmt)
ax.xaxis.set_major_formatter(xticks)

plt.show()

Link to the above solution: Pyplot: using percentage on x axis


回答 0

这已经晚了几个月,但是我使用matplotlib 创建了PR#6251以添加一个新PercentFormatter类。使用此类,您只需要一行就可以重新格式化轴(如果算上的导入,则需要两行matplotlib.ticker):

import ...
import matplotlib.ticker as mtick

ax = df['myvar'].plot(kind='bar')
ax.yaxis.set_major_formatter(mtick.PercentFormatter())

PercentFormatter()接受三个参数,xmaxdecimalssymbolxmax允许您设置对应于轴上100%的值。如果数据的范围是0.0到1.0,并且要显示的范围是0%到100%,那么这很好。做吧PercentFormatter(1.0)

另外两个参数允许您设置小数点和符号后的位数。它们分别默认为None'%'decimals=None会根据您显示的轴数自动设置小数点的数量。

更新资料

PercentFormatter 已在2.1.0版的Matplotlib中引入。

This is a few months late, but I have created PR#6251 with matplotlib to add a new PercentFormatter class. With this class you just need one line to reformat your axis (two if you count the import of matplotlib.ticker):

import ...
import matplotlib.ticker as mtick

ax = df['myvar'].plot(kind='bar')
ax.yaxis.set_major_formatter(mtick.PercentFormatter())

PercentFormatter() accepts three arguments, xmax, decimals, symbol. xmax allows you to set the value that corresponds to 100% on the axis. This is nice if you have data from 0.0 to 1.0 and you want to display it from 0% to 100%. Just do PercentFormatter(1.0).

The other two parameters allow you to set the number of digits after the decimal point and the symbol. They default to None and '%', respectively. decimals=None will automatically set the number of decimal points based on how much of the axes you are showing.

Update

PercentFormatter was introduced into Matplotlib proper in version 2.1.0.


回答 1

熊猫数据框图将为ax您返回,然后您就可以开始操纵轴了。

import pandas as pd
import numpy as np

df = pd.DataFrame(np.random.randn(100,5))

# you get ax from here
ax = df.plot()
type(ax)  # matplotlib.axes._subplots.AxesSubplot

# manipulate
vals = ax.get_yticks()
ax.set_yticklabels(['{:,.2%}'.format(x) for x in vals])

在此处输入图片说明

pandas dataframe plot will return the ax for you, And then you can start to manipulate the axes whatever you want.

import pandas as pd
import numpy as np

df = pd.DataFrame(np.random.randn(100,5))

# you get ax from here
ax = df.plot()
type(ax)  # matplotlib.axes._subplots.AxesSubplot

# manipulate
vals = ax.get_yticks()
ax.set_yticklabels(['{:,.2%}'.format(x) for x in vals])

enter image description here


回答 2

建勋的解决方案为我完成了工作,但打破了窗口左下方的y值指示器。

我最终FuncFormatter改为使用它(并且还删除了此处建议的不必要的尾随零):

import pandas as pd
import numpy as np
from matplotlib.ticker import FuncFormatter

df = pd.DataFrame(np.random.randn(100,5))

ax = df.plot()
ax.yaxis.set_major_formatter(FuncFormatter(lambda y, _: '{:.0%}'.format(y))) 

一般来说,我建议使用FuncFormatter标签格式:它可靠且用途广泛。

在此处输入图片说明

Jianxun‘s solution did the job for me but broke the y value indicator at the bottom left of the window.

I ended up using FuncFormatterinstead (and also stripped the uneccessary trailing zeroes as suggested here):

import pandas as pd
import numpy as np
from matplotlib.ticker import FuncFormatter

df = pd.DataFrame(np.random.randn(100,5))

ax = df.plot()
ax.yaxis.set_major_formatter(FuncFormatter(lambda y, _: '{:.0%}'.format(y))) 

Generally speaking I’d recommend using FuncFormatter for label formatting: it’s reliable, and versatile.

enter image description here


回答 3

对于那些正在寻找快速一线客的人:

plt.gca().set_yticklabels(['{:.0f}%'.format(x*100) for x in plt.gca().get_yticks()]) 

或者,如果您使用Latex作为轴文本格式程序,则必须添加一个反斜杠“ \”

plt.gca().set_yticklabels(['{:.0f}\%'.format(x*100) for x in plt.gca().get_yticks()]) 

For those who are looking for the quick one-liner:

plt.gca().set_yticklabels(['{:.0f}%'.format(x*100) for x in plt.gca().get_yticks()]) 

Or if you are using Latex as the axis text formatter, you have to add one backslash ‘\’

plt.gca().set_yticklabels(['{:.0f}\%'.format(x*100) for x in plt.gca().get_yticks()]) 

回答 4

我提出了一种替代方法 seaborn

工作代码:

import pandas as pd
import seaborn as sns
data=np.random.rand(10,2)*100
df = pd.DataFrame(data, columns=['A', 'B'])
ax= sns.lineplot(data=df, markers= True)
ax.set(xlabel='xlabel', ylabel='ylabel', title='title')
#changing ylables ticks
y_value=['{:,.2f}'.format(x) + '%' for x in ax.get_yticks()]
ax.set_yticklabels(y_value)

在此处输入图片说明

I propose an alternative method using seaborn

Working code:

import pandas as pd
import seaborn as sns
data=np.random.rand(10,2)*100
df = pd.DataFrame(data, columns=['A', 'B'])
ax= sns.lineplot(data=df, markers= True)
ax.set(xlabel='xlabel', ylabel='ylabel', title='title')
#changing ylables ticks
y_value=['{:,.2f}'.format(x) + '%' for x in ax.get_yticks()]
ax.set_yticklabels(y_value)

enter image description here


回答 5

我玩游戏迟到了,但是我才意识到:ax可以替换为plt.gca()对于那些不使用轴而只是使用子图的人来说,为。

回响@Mad Physicist答案,使用该软件包PercentFormatter将是:

import matplotlib.ticker as mtick

plt.gca().yaxis.set_major_formatter(mtick.PercentFormatter(1))
#if you already have ticks in the 0 to 1 range. Otherwise see their answer

I’m late to the game but I just realize this: ax can be replaced with plt.gca() for those who are not using axes and just subplots.

Echoing @Mad Physicist answer, using the package PercentFormatter it would be:

import matplotlib.ticker as mtick

plt.gca().yaxis.set_major_formatter(mtick.PercentFormatter(1))
#if you already have ticks in the 0 to 1 range. Otherwise see their answer

将文本放在matplotlib图的左上角

问题:将文本放在matplotlib图的左上角

如何在matplotlib图形的左上角(或右上角)放置文本,例如,左上角图例所在的位置,还是绘图的顶部,但在左上角?例如,如果它是一个plt.scatter(),那么将在散点图的平方内放置一些东西,将其放在最左上角。

我想在不理想地知道例如散点图的比例的情况下进行此操作,因为它会随数据集的不同而变化。我只希望它的文字大致在左上方,或大致在右上方。使用图例类型定位时,它无论如何都不应与任何散点图点重叠。

谢谢!

How can I put text in the top left (or top right) corner of a matplotlib figure, e.g. where a top left legend would be, or on top of the plot but in the top left corner? E.g. if it’s a plt.scatter(), then something that would be within the square of the scatter, put in the top left most corner.

I’d like to do this without ideally knowing the scale of the scatterplot being plotted for example, since it will change from dataset to data set. I just want it the text to be roughly in the upper left, or roughly in the upper right. With legend type positioning it should not overlap with any scatter plot points anyway.

thanks!


回答 0

您可以使用text

text(x, y, s, fontsize=12)

text 可以相对于轴指定坐标,因此文本的位置将与绘图的大小无关:

默认转换指定文本在数据坐标中,或者,您也可以在坐标轴中指定文本(0,0是左下角,而1,1是右上角)。下面的示例将文本放置在轴的中心::

text(0.5, 0.5,'matplotlib',
     horizontalalignment='center',
     verticalalignment='center',
     transform = ax.transAxes)

要防止文本干扰散点图的任何点,都是比较困难的。比较简单的方法是将y_axis(的ymax ylim((ymin,ymax))轴)设置为比点的最大y坐标高一点的值。这样,您将始终拥有文本的可用空间。

编辑:这里有一个例子:

In [17]: from pylab import figure, text, scatter, show
In [18]: f = figure()
In [19]: ax = f.add_subplot(111)
In [20]: scatter([3,5,2,6,8],[5,3,2,1,5])
Out[20]: <matplotlib.collections.CircleCollection object at 0x0000000007439A90>
In [21]: text(0.1, 0.9,'matplotlib', ha='center', va='center', transform=ax.transAxes)
Out[21]: <matplotlib.text.Text object at 0x0000000007415B38>
In [22]:

在此处输入图片说明

ha和va参数设置文本相对于插入点的对齐方式。即。ha =’left’是一个很好的设置,可以防止在手动缩小(变窄)帧时长文本从左轴移出。

You can use text.

text(x, y, s, fontsize=12)

text coordinates can be given relative to the axis, so the position of your text will be independent of the size of the plot:

The default transform specifies that text is in data coords, alternatively, you can specify text in axis coords (0,0 is lower-left and 1,1 is upper-right). The example below places text in the center of the axes::

text(0.5, 0.5,'matplotlib',
     horizontalalignment='center',
     verticalalignment='center',
     transform = ax.transAxes)

To prevent the text to interfere with any point of your scatter is more difficult afaik. The easier method is to set y_axis (ymax in ylim((ymin,ymax))) to a value a bit higher than the max y-coordinate of your points. In this way you will always have this free space for the text.

EDIT: here you have an example:

In [17]: from pylab import figure, text, scatter, show
In [18]: f = figure()
In [19]: ax = f.add_subplot(111)
In [20]: scatter([3,5,2,6,8],[5,3,2,1,5])
Out[20]: <matplotlib.collections.CircleCollection object at 0x0000000007439A90>
In [21]: text(0.1, 0.9,'matplotlib', ha='center', va='center', transform=ax.transAxes)
Out[21]: <matplotlib.text.Text object at 0x0000000007415B38>
In [22]:

enter image description here

The ha and va parameters set the alignment of your text relative to the insertion point. ie. ha=’left’ is a good set to prevent a long text to go out of the left axis when the frame is reduced (made narrower) manually.


回答 1

一种解决方案是使用该plt.legend功能,即使您不需要实际的图例。您可以使用loc关键字词指定图例框的位置。可以在此网站上找到更多信息但我还提供了一个示例,说明如何放置图例:

ax.scatter(xa,ya, marker='o', s=20, c="lightgreen", alpha=0.9)
ax.scatter(xb,yb, marker='o', s=20, c="dodgerblue", alpha=0.9)
ax.scatter(xc,yc marker='o', s=20, c="firebrick", alpha=1.0)
ax.scatter(xd,xd,xd, marker='o', s=20, c="goldenrod", alpha=0.9)
line1 = Line2D(range(10), range(10), marker='o', color="goldenrod")
line2 = Line2D(range(10), range(10), marker='o',color="firebrick")
line3 = Line2D(range(10), range(10), marker='o',color="lightgreen")
line4 = Line2D(range(10), range(10), marker='o',color="dodgerblue")
plt.legend((line1,line2,line3, line4),('line1','line2', 'line3', 'line4'),numpoints=1, loc=2) 

请注意,因为loc=2,图例位于图的左上角。并且如果文本与图重叠,则可以使用来使其变小legend.fontsize,从而使图例变小。

One solution would be to use the plt.legend function, even if you don’t want an actual legend. You can specify the placement of the legend box by using the loc keyterm. More information can be found at this website but I’ve also included an example showing how to place a legend:

ax.scatter(xa,ya, marker='o', s=20, c="lightgreen", alpha=0.9)
ax.scatter(xb,yb, marker='o', s=20, c="dodgerblue", alpha=0.9)
ax.scatter(xc,yc marker='o', s=20, c="firebrick", alpha=1.0)
ax.scatter(xd,xd,xd, marker='o', s=20, c="goldenrod", alpha=0.9)
line1 = Line2D(range(10), range(10), marker='o', color="goldenrod")
line2 = Line2D(range(10), range(10), marker='o',color="firebrick")
line3 = Line2D(range(10), range(10), marker='o',color="lightgreen")
line4 = Line2D(range(10), range(10), marker='o',color="dodgerblue")
plt.legend((line1,line2,line3, line4),('line1','line2', 'line3', 'line4'),numpoints=1, loc=2) 

Note that because loc=2, the legend is in the upper-left corner of the plot. And if the text overlaps with the plot, you can make it smaller by using legend.fontsize, which will then make the legend smaller.


如何为上限设置“自动”,但通过matplotlib.pyplot保持固定的下限

问题:如何为上限设置“自动”,但通过matplotlib.pyplot保持固定的下限

我想将y轴的上限设置为“自动”,但我想使y轴的下限始终为零。我尝试了“自动”和“自动调整范围”,但它们似乎不起作用。先感谢您。

这是我的代码:

import matplotlib.pyplot as plt

def plot(results_plt,title,filename):

    ############################
    # Plot results

    # mirror result table such that each parameter forms an own data array
    plt.cla()
    #print results_plt
    XY_results = []

    XY_results = zip( *results_plt)

    plt.plot(XY_results[0], XY_results[2], marker = ".")

    plt.title('%s' % (title) )
    plt.xlabel('Input Voltage [V]')
    plt.ylabel('Input Current [mA]')

    plt.grid(True)
    plt.xlim(3.0, 4.2)  #***I want to keep these values fixed"
    plt.ylim([0, 80]) #****CHANGE**** I want to change '80' to auto, but still keep 0 as the lower limit 
    plt.savefig(path+filename+'.png')

I want to set the upper limit of the y-axis to ‘auto’, but I want to keep the lower limit of the y-axis to always be zero. I tried ‘auto’ and ‘autorange’, but those don’t seem to work. Thank you in advance.

Here is my code:

import matplotlib.pyplot as plt

def plot(results_plt,title,filename):

    ############################
    # Plot results

    # mirror result table such that each parameter forms an own data array
    plt.cla()
    #print results_plt
    XY_results = []

    XY_results = zip( *results_plt)

    plt.plot(XY_results[0], XY_results[2], marker = ".")

    plt.title('%s' % (title) )
    plt.xlabel('Input Voltage [V]')
    plt.ylabel('Input Current [mA]')

    plt.grid(True)
    plt.xlim(3.0, 4.2)  #***I want to keep these values fixed"
    plt.ylim([0, 80]) #****CHANGE**** I want to change '80' to auto, but still keep 0 as the lower limit 
    plt.savefig(path+filename+'.png')

回答 0

您可以通过只leftrightset_xlim

plt.gca().set_xlim(left=0)

对于y轴,请使用bottomtop

plt.gca().set_ylim(bottom=0)

You can pass just left or right to set_xlim:

plt.gca().set_xlim(left=0)

For the y axis, use bottom or top:

plt.gca().set_ylim(bottom=0)

回答 1

只需设置xlim以下限制之一:

plt.xlim(xmin=0)

Just set xlim for one of the limits:

plt.xlim(xmin=0)

回答 2

如上所述,根据matplotlib文档,ax可以使用类的set_xlim方法设置给定轴的x极限matplotlib.axes.Axes

例如,

>>> ax.set_xlim(left_limit, right_limit)
>>> ax.set_xlim((left_limit, right_limit))
>>> ax.set_xlim(left=left_limit, right=right_limit)

一个限制可以保持不变(例如,左边限制):

>>> ax.set_xlim((None, right_limit))
>>> ax.set_xlim(None, right_limit)
>>> ax.set_xlim(left=None, right=right_limit)
>>> ax.set_xlim(right=right_limit)

要设置当前轴的x极限,matplotlib.pyplot模块包含xlim仅包装matplotlib.pyplot.gca和的函数 matplotlib.axes.Axes.set_xlim

def xlim(*args, **kwargs):
    ax = gca()
    if not args and not kwargs:
        return ax.get_xlim()
    ret = ax.set_xlim(*args, **kwargs)
    return ret

同样,对于y限制,请使用matplotlib.axes.Axes.set_ylimmatplotlib.pyplot.ylim。关键字参数为topbottom

As aforementioned and according to the matplotlib documentation, the x-limits of a given axis ax can be set using the set_xlim method of the matplotlib.axes.Axes class.

For instance,

>>> ax.set_xlim(left_limit, right_limit)
>>> ax.set_xlim((left_limit, right_limit))
>>> ax.set_xlim(left=left_limit, right=right_limit)

One limit may be left unchanged (e.g. the left limit):

>>> ax.set_xlim((None, right_limit))
>>> ax.set_xlim(None, right_limit)
>>> ax.set_xlim(left=None, right=right_limit)
>>> ax.set_xlim(right=right_limit)

To set the x-limits of the current axis, the matplotlib.pyplot module contains the xlim function that just wraps matplotlib.pyplot.gca and matplotlib.axes.Axes.set_xlim.

def xlim(*args, **kwargs):
    ax = gca()
    if not args and not kwargs:
        return ax.get_xlim()
    ret = ax.set_xlim(*args, **kwargs)
    return ret

Similarly, for the y-limits, use matplotlib.axes.Axes.set_ylim or matplotlib.pyplot.ylim. The keyword arguments are top and bottom.


回答 3

只需在@silvio的点上添加一个点:如果使用轴绘制像figure, ax1 = plt.subplots(1,2,1)。然后ax1.set_xlim(xmin = 0)也可以!

Just add a point on @silvio ‘s: if you use axis to plot like figure, ax1 = plt.subplots(1,2,1). Then ax1.set_xlim(xmin = 0) also works!


Python Matplotlib Y轴在图的右侧滴答

问题:Python Matplotlib Y轴在图的右侧滴答

我有一个简单的线图,需要将y轴刻度从图的(默认)左侧移到右侧。有关如何执行此操作的任何想法?

I have a simple line plot and need to move the y-axis ticks from the (default) left side of the plot to the right side. Any thoughts on how to do this?


回答 0

ax.yaxis.tick_right()

例如:

from matplotlib import pyplot as plt

f = plt.figure()
ax = f.add_subplot(111)
ax.yaxis.tick_right()
plt.plot([2,3,4,5])
plt.show()

在此处输入图片说明

Use ax.yaxis.tick_right()

for example:

from matplotlib import pyplot as plt

f = plt.figure()
ax = f.add_subplot(111)
ax.yaxis.tick_right()
plt.plot([2,3,4,5])
plt.show()

enter image description here


回答 1

对于正确的标签,请使用ax.yaxis.set_label_position("right"),即:

f = plt.figure()
ax = f.add_subplot(111)
ax.yaxis.tick_right()
ax.yaxis.set_label_position("right")
plt.plot([2,3,4,5])
ax.set_xlabel("$x$ /mm")
ax.set_ylabel("$y$ /mm")
plt.show()

For right labels use ax.yaxis.set_label_position("right"), i.e.:

f = plt.figure()
ax = f.add_subplot(111)
ax.yaxis.tick_right()
ax.yaxis.set_label_position("right")
plt.plot([2,3,4,5])
ax.set_xlabel("$x$ /mm")
ax.set_ylabel("$y$ /mm")
plt.show()

回答 2

joaquin的答案有效,但具有消除轴左侧刻度线的副作用。要解决此问题,tick_right()请调用set_ticks_position('both')。修改后的示例:

from matplotlib import pyplot as plt

f = plt.figure()
ax = f.add_subplot(111)
ax.yaxis.tick_right()
ax.yaxis.set_ticks_position('both')
plt.plot([2,3,4,5])
plt.show()

结果是在两边都带有刻度线的图,但在右边的刻度线标签。

在此处输入图片说明

joaquin’s answer works, but has the side effect of removing ticks from the left side of the axes. To fix this, follow up tick_right() with a call to set_ticks_position('both'). A revised example:

from matplotlib import pyplot as plt

f = plt.figure()
ax = f.add_subplot(111)
ax.yaxis.tick_right()
ax.yaxis.set_ticks_position('both')
plt.plot([2,3,4,5])
plt.show()

The result is a plot with ticks on both sides, but tick labels on the right.

enter image description here


回答 3

就像有人问的那样(就像我一样),当使用subplot2grid时这也是可能的。例如:

import matplotlib.pyplot as plt
plt.subplot2grid((3,2), (0,1), rowspan=3)
plt.plot([2,3,4,5])
plt.tick_params(axis='y', which='both', labelleft='off', labelright='on')
plt.show()

它将显示以下内容:

在此处输入图片说明

Just is case somebody asks (like I did), this is also possible when one uses subplot2grid. For example:

import matplotlib.pyplot as plt
plt.subplot2grid((3,2), (0,1), rowspan=3)
plt.plot([2,3,4,5])
plt.tick_params(axis='y', which='both', labelleft='off', labelright='on')
plt.show()

It will show this:

enter image description here


用PyPlot绘制平滑线

问题:用PyPlot绘制平滑线

我有以下绘制图形的简单脚本:

import matplotlib.pyplot as plt
import numpy as np

T = np.array([6, 7, 8, 9, 10, 11, 12])
power = np.array([1.53E+03, 5.92E+02, 2.04E+02, 7.24E+01, 2.72E+01, 1.10E+01, 4.70E+00])

plt.plot(T,power)
plt.show()

就目前而言,这条线从一条直线到另一条直线看起来不错,但在我看来可能会更好。我想要的是使两点之间的线平滑。在Gnuplot中,我会用绘制smooth cplines

在PyPlot中有一种简单的方法吗?我已经找到了一些教程,但是它们似乎都相当复杂。

I’ve got the following simple script that plots a graph:

import matplotlib.pyplot as plt
import numpy as np

T = np.array([6, 7, 8, 9, 10, 11, 12])
power = np.array([1.53E+03, 5.92E+02, 2.04E+02, 7.24E+01, 2.72E+01, 1.10E+01, 4.70E+00])

plt.plot(T,power)
plt.show()

As it is now, the line goes straight from point to point which looks ok, but could be better in my opinion. What I want is to smooth the line between the points. In Gnuplot I would have plotted with smooth cplines.

Is there an easy way to do this in PyPlot? I’ve found some tutorials, but they all seem rather complex.


回答 0

您可以用来scipy.interpolate.spline自己整理数据:

from scipy.interpolate import spline

# 300 represents number of points to make between T.min and T.max
xnew = np.linspace(T.min(), T.max(), 300)  

power_smooth = spline(T, power, xnew)

plt.plot(xnew,power_smooth)
plt.show()

scipy 0.19.0中已弃用样条线,请改用BSpline类。

从切换splineBSpline复制并不是简单的复制/粘贴操作,需要进行一些调整:

from scipy.interpolate import make_interp_spline, BSpline

# 300 represents number of points to make between T.min and T.max
xnew = np.linspace(T.min(), T.max(), 300) 

spl = make_interp_spline(T, power, k=3)  # type: BSpline
power_smooth = spl(xnew)

plt.plot(xnew, power_smooth)
plt.show()

之前: 屏幕截图1

后: 屏幕截图2

You could use scipy.interpolate.spline to smooth out your data yourself:

from scipy.interpolate import spline

# 300 represents number of points to make between T.min and T.max
xnew = np.linspace(T.min(), T.max(), 300)  

power_smooth = spline(T, power, xnew)

plt.plot(xnew,power_smooth)
plt.show()

spline is deprecated in scipy 0.19.0, use BSpline class instead.

Switching from spline to BSpline isn’t a straightforward copy/paste and requires a little tweaking:

from scipy.interpolate import make_interp_spline, BSpline

# 300 represents number of points to make between T.min and T.max
xnew = np.linspace(T.min(), T.max(), 300) 

spl = make_interp_spline(T, power, k=3)  # type: BSpline
power_smooth = spl(xnew)

plt.plot(xnew, power_smooth)
plt.show()

Before: screenshot 1

After: screenshot 2


回答 1

对于此示例,样条曲线效果很好,但是如果函数固有地不平滑,并且您想要平滑的版本,则还可以尝试:

from scipy.ndimage.filters import gaussian_filter1d

ysmoothed = gaussian_filter1d(y, sigma=2)
plt.plot(x, ysmoothed)
plt.show()

如果增加sigma,可以获得更平滑的功能。

请谨慎处理这一内容。它会修改原始值,可能不是您想要的。

For this example spline works well, but if the function is not smooth inherently and you want to have smoothed version you can also try:

from scipy.ndimage.filters import gaussian_filter1d

ysmoothed = gaussian_filter1d(y, sigma=2)
plt.plot(x, ysmoothed)
plt.show()

if you increase sigma you can get a more smoothed function.

Proceed with caution with this one. It modifies the original values and may not be what you want.


回答 2

我认为您的意思是曲线拟合,而不是从您的问题的上下文来看抗锯齿。PyPlot没有任何内置的这种支持,但你可以很容易地实现一些基本的曲线拟合自己,喜欢看到的代码在这里,或者如果你使用GuiQwt它有一个曲线拟合模块。(您可能也可以从SciPy窃取代码来执行此操作)。

I presume you mean curve-fitting and not anti-aliasing from the context of your question. PyPlot doesn’t have any built-in support for this, but you can easily implement some basic curve-fitting yourself, like the code seen here, or if you’re using GuiQwt it has a curve fitting module. (You could probably also steal the code from SciPy to do this as well).


回答 3

有关scipy.interpolate一些示例,请参见文档。

以下示例演示了其在线性和三次样条插值中的用法:

>>> from scipy.interpolate import interp1d

>>> x = np.linspace(0, 10, num=11, endpoint=True)
>>> y = np.cos(-x**2/9.0)
>>> f = interp1d(x, y)
>>> f2 = interp1d(x, y, kind='cubic')

>>> xnew = np.linspace(0, 10, num=41, endpoint=True)
>>> import matplotlib.pyplot as plt
>>> plt.plot(x, y, 'o', xnew, f(xnew), '-', xnew, f2(xnew), '--')
>>> plt.legend(['data', 'linear', 'cubic'], loc='best')
>>> plt.show()

在此处输入图片说明

See the scipy.interpolate documentation for some examples.

The following example demonstrates its use, for linear and cubic spline interpolation:

>>> from scipy.interpolate import interp1d

>>> x = np.linspace(0, 10, num=11, endpoint=True)
>>> y = np.cos(-x**2/9.0)
>>> f = interp1d(x, y)
>>> f2 = interp1d(x, y, kind='cubic')

>>> xnew = np.linspace(0, 10, num=41, endpoint=True)
>>> import matplotlib.pyplot as plt
>>> plt.plot(x, y, 'o', xnew, f(xnew), '-', xnew, f2(xnew), '--')
>>> plt.legend(['data', 'linear', 'cubic'], loc='best')
>>> plt.show()

enter image description here


在matplotlib中将x轴移动到绘图的顶部

问题:在matplotlib中将x轴移动到绘图的顶部

基于关于matplotlib中的热图的问题,我想将x轴标题移动到图的顶部。

import matplotlib.pyplot as plt
import numpy as np
column_labels = list('ABCD')
row_labels = list('WXYZ')
data = np.random.rand(4,4)
fig, ax = plt.subplots()
heatmap = ax.pcolor(data, cmap=plt.cm.Blues)

# put the major ticks at the middle of each cell
ax.set_xticks(np.arange(data.shape[0])+0.5, minor=False)
ax.set_yticks(np.arange(data.shape[1])+0.5, minor=False)

# want a more natural, table-like display
ax.invert_yaxis()
ax.xaxis.set_label_position('top') # <-- This doesn't work!

ax.set_xticklabels(row_labels, minor=False)
ax.set_yticklabels(column_labels, minor=False)
plt.show()

但是,调用matplotlib的set_label_position(如上所述)似乎没有达到预期的效果。这是我的输出:

在此处输入图片说明

我究竟做错了什么?

Based on this question about heatmaps in matplotlib, I wanted to move the x-axis titles to the top of the plot.

import matplotlib.pyplot as plt
import numpy as np
column_labels = list('ABCD')
row_labels = list('WXYZ')
data = np.random.rand(4,4)
fig, ax = plt.subplots()
heatmap = ax.pcolor(data, cmap=plt.cm.Blues)

# put the major ticks at the middle of each cell
ax.set_xticks(np.arange(data.shape[0])+0.5, minor=False)
ax.set_yticks(np.arange(data.shape[1])+0.5, minor=False)

# want a more natural, table-like display
ax.invert_yaxis()
ax.xaxis.set_label_position('top') # <-- This doesn't work!

ax.set_xticklabels(row_labels, minor=False)
ax.set_yticklabels(column_labels, minor=False)
plt.show()

However, calling matplotlib’s set_label_position (as notated above) doesn’t seem to have the desired effect. Here’s my output:

enter image description here

What am I doing wrong?


回答 0

ax.xaxis.tick_top()

将刻度线放在图像的顶部。命令

ax.set_xlabel('X LABEL')    
ax.xaxis.set_label_position('top') 

影响标签,而不影响刻度线。

import matplotlib.pyplot as plt
import numpy as np
column_labels = list('ABCD')
row_labels = list('WXYZ')
data = np.random.rand(4, 4)
fig, ax = plt.subplots()
heatmap = ax.pcolor(data, cmap=plt.cm.Blues)

# put the major ticks at the middle of each cell
ax.set_xticks(np.arange(data.shape[1]) + 0.5, minor=False)
ax.set_yticks(np.arange(data.shape[0]) + 0.5, minor=False)

# want a more natural, table-like display
ax.invert_yaxis()
ax.xaxis.tick_top()

ax.set_xticklabels(column_labels, minor=False)
ax.set_yticklabels(row_labels, minor=False)
plt.show()

在此处输入图片说明

Use

ax.xaxis.tick_top()

to place the tick marks at the top of the image. The command

ax.set_xlabel('X LABEL')    
ax.xaxis.set_label_position('top') 

affects the label, not the tick marks.

import matplotlib.pyplot as plt
import numpy as np
column_labels = list('ABCD')
row_labels = list('WXYZ')
data = np.random.rand(4, 4)
fig, ax = plt.subplots()
heatmap = ax.pcolor(data, cmap=plt.cm.Blues)

# put the major ticks at the middle of each cell
ax.set_xticks(np.arange(data.shape[1]) + 0.5, minor=False)
ax.set_yticks(np.arange(data.shape[0]) + 0.5, minor=False)

# want a more natural, table-like display
ax.invert_yaxis()
ax.xaxis.tick_top()

ax.set_xticklabels(column_labels, minor=False)
ax.set_yticklabels(row_labels, minor=False)
plt.show()

enter image description here


回答 1

您想要set_ticks_position而不是set_label_position

ax.xaxis.set_ticks_position('top') # the rest is the same

这给了我:

在此处输入图片说明

You want set_ticks_position rather than set_label_position:

ax.xaxis.set_ticks_position('top') # the rest is the same

This gives me:

enter image description here


回答 2

tick_params对于设置刻度属性非常有用。可以使用以下命令将标签移到顶部:

    ax.tick_params(labelbottom=False,labeltop=True)

tick_params is very useful for setting tick properties. Labels can be moved to the top with:

    ax.tick_params(labelbottom=False,labeltop=True)

回答 3

如果要让刻度(而不是标签)显示在顶部和底部(而不仅仅是顶部),则必须做一些额外的按摩。我可以做到的唯一方法是对unutbu的代码进行较小的更改:

import matplotlib.pyplot as plt
import numpy as np
column_labels = list('ABCD')
row_labels = list('WXYZ')
data = np.random.rand(4, 4)
fig, ax = plt.subplots()
heatmap = ax.pcolor(data, cmap=plt.cm.Blues)

# put the major ticks at the middle of each cell
ax.set_xticks(np.arange(data.shape[1]) + 0.5, minor=False)
ax.set_yticks(np.arange(data.shape[0]) + 0.5, minor=False)

# want a more natural, table-like display
ax.invert_yaxis()
ax.xaxis.tick_top()
ax.xaxis.set_ticks_position('both') # THIS IS THE ONLY CHANGE

ax.set_xticklabels(column_labels, minor=False)
ax.set_yticklabels(row_labels, minor=False)
plt.show()

输出:

在此处输入图片说明

You’ve got to do some extra massaging if you want the ticks (not labels) to show up on the top and bottom (not just the top). The only way I could do this is with a minor change to unutbu’s code:

import matplotlib.pyplot as plt
import numpy as np
column_labels = list('ABCD')
row_labels = list('WXYZ')
data = np.random.rand(4, 4)
fig, ax = plt.subplots()
heatmap = ax.pcolor(data, cmap=plt.cm.Blues)

# put the major ticks at the middle of each cell
ax.set_xticks(np.arange(data.shape[1]) + 0.5, minor=False)
ax.set_yticks(np.arange(data.shape[0]) + 0.5, minor=False)

# want a more natural, table-like display
ax.invert_yaxis()
ax.xaxis.tick_top()
ax.xaxis.set_ticks_position('both') # THIS IS THE ONLY CHANGE

ax.set_xticklabels(column_labels, minor=False)
ax.set_yticklabels(row_labels, minor=False)
plt.show()

Output:

enter image description here


如何在Python中使用Matplotlib绘制带有数据列表的直方图?

问题:如何在Python中使用Matplotlib绘制带有数据列表的直方图?

我正在尝试使用该matplotlib.hist()函数绘制直方图,但是我不确定该怎么做。

我有一个清单

probability = [0.3602150537634409, 0.42028985507246375, 
  0.373117033603708, 0.36813186813186816, 0.32517482517482516, 
  0.4175257731958763, 0.41025641025641024, 0.39408866995073893, 
  0.4143222506393862, 0.34, 0.391025641025641, 0.3130841121495327, 
  0.35398230088495575]

和名称(字符串)列表。

如何使概率作为每个小节的y值,并命名为x值?

I am trying to plot a histogram using the matplotlib.hist() function but I am not sure how to do it.

I have a list

probability = [0.3602150537634409, 0.42028985507246375, 
  0.373117033603708, 0.36813186813186816, 0.32517482517482516, 
  0.4175257731958763, 0.41025641025641024, 0.39408866995073893, 
  0.4143222506393862, 0.34, 0.391025641025641, 0.3130841121495327, 
  0.35398230088495575]

and a list of names(strings).

How do I make the probability as my y-value of each bar and names as x-values?


回答 0

如果您想要直方图,则无需在x值上附加任何“名称”,因为在x轴上您将具有数据仓:

import matplotlib.pyplot as plt
import numpy as np
%matplotlib inline
np.random.seed(42)
x = np.random.normal(size=1000)
plt.hist(x, density=True, bins=30)  # `density=False` would make counts
plt.ylabel('Probability')
plt.xlabel('Data');

在此处输入图片说明

您可以通过PDF线条,标题和图例使直方图更奇特:

import scipy.stats as st
plt.hist(x, density=True, bins=30, label="Data")
mn, mx = plt.xlim()
plt.xlim(mn, mx)
kde_xs = np.linspace(mn, mx, 301)
kde = st.gaussian_kde(x)
plt.plot(kde_xs, kde.pdf(kde_xs), label="PDF")
plt.legend(loc="upper left")
plt.ylabel('Probability')
plt.xlabel('Data')
plt.title("Histogram");

在此处输入图片说明

但是,如果您的数据点数量有限(例如在OP中),则条形图可以更好地表示您的数据(然后您可以在x轴上附加标签):

x = np.arange(3)
plt.bar(x, height=[1,2,3])
plt.xticks(x, ['a','b','c'])

在此处输入图片说明

If you want a histogram, you don’t need to attach any ‘names’ to x-values, as on x-axis you would have data bins:

import matplotlib.pyplot as plt
import numpy as np
%matplotlib inline
np.random.seed(42)
x = np.random.normal(size=1000)
plt.hist(x, density=True, bins=30)  # `density=False` would make counts
plt.ylabel('Probability')
plt.xlabel('Data');

enter image description here

You can make your histogram a bit fancier with PDF line, titles, and legend:

import scipy.stats as st
plt.hist(x, density=True, bins=30, label="Data")
mn, mx = plt.xlim()
plt.xlim(mn, mx)
kde_xs = np.linspace(mn, mx, 301)
kde = st.gaussian_kde(x)
plt.plot(kde_xs, kde.pdf(kde_xs), label="PDF")
plt.legend(loc="upper left")
plt.ylabel('Probability')
plt.xlabel('Data')
plt.title("Histogram");

enter image description here

However, if you have limited number of data points, like in OP, a bar plot would make more sense to represent your data (then you may attach labels to x-axis):

x = np.arange(3)
plt.bar(x, height=[1,2,3])
plt.xticks(x, ['a','b','c'])

enter image description here


回答 1

如果尚未安装matplotlib,请尝试使用该命令。

> pip install matplotlib

图书馆进口

import matplotlib.pyplot as plot

直方图数据:

plot.hist(weightList,density=1, bins=20) 
plot.axis([50, 110, 0, 0.06]) 
#axis([xmin,xmax,ymin,ymax])
plot.xlabel('Weight')
plot.ylabel('Probability')

显示直方图

plot.show()

和输出是这样的:

在此处输入图片说明

If you haven’t installed matplotlib yet just try the command.

> pip install matplotlib

Library import

import matplotlib.pyplot as plot

The histogram data:

plot.hist(weightList,density=1, bins=20) 
plot.axis([50, 110, 0, 0.06]) 
#axis([xmin,xmax,ymin,ymax])
plot.xlabel('Weight')
plot.ylabel('Probability')

Display histogram

plot.show()

And the output is like :

enter image description here


回答 2

尽管问题似乎要求使用以下方法绘制直方图 matplotlib.hist()函数,但可以使用问题的后半部分,即使用给定的概率作为直方图的y值并使用给定的名称(字符串)作为直方图的y值,这可以说是不可行的。 x值。

我假设一个名称列表示例与绘制该图的给定概率相对应。一个简单的条形图可以解决给定问题。可以使用以下代码:

import matplotlib.pyplot as plt
probability = [0.3602150537634409, 0.42028985507246375, 
  0.373117033603708, 0.36813186813186816, 0.32517482517482516, 
  0.4175257731958763, 0.41025641025641024, 0.39408866995073893, 
  0.4143222506393862, 0.34, 0.391025641025641, 0.3130841121495327, 
  0.35398230088495575]
names = ['name1', 'name2', 'name3', 'name4', 'name5', 'name6', 'name7', 'name8', 'name9',
'name10', 'name11', 'name12', 'name13'] #sample names
plt.bar(names, probability)
plt.xticks(names)
plt.yticks(probability) #This may be included or excluded as per need
plt.xlabel('Names')
plt.ylabel('Probability')

Though the question appears to be demanding plotting a histogram using matplotlib.hist() function, it can arguably be not done using the same as the latter part of the question demands to use the given probabilities as the y-values of bars and given names(strings) as the x-values.

I’m assuming a sample list of names corresponding to given probabilities to draw the plot. A simple bar plot serves the purpose here for the given problem. The following code can be used:

import matplotlib.pyplot as plt
probability = [0.3602150537634409, 0.42028985507246375, 
  0.373117033603708, 0.36813186813186816, 0.32517482517482516, 
  0.4175257731958763, 0.41025641025641024, 0.39408866995073893, 
  0.4143222506393862, 0.34, 0.391025641025641, 0.3130841121495327, 
  0.35398230088495575]
names = ['name1', 'name2', 'name3', 'name4', 'name5', 'name6', 'name7', 'name8', 'name9',
'name10', 'name11', 'name12', 'name13'] #sample names
plt.bar(names, probability)
plt.xticks(names)
plt.yticks(probability) #This may be included or excluded as per need
plt.xlabel('Names')
plt.ylabel('Probability')

回答 3

这是一种非常绕行的方法,但是如果要创建直方图,在该直方图中您已经知道bin值但没有源数据,则可以使用该np.random.randint函数在每个范围内生成正确数量的值bin用于绘制的hist函数,例如:

import numpy as np
import matplotlib.pyplot as plt

data = [np.random.randint(0, 9, *desired y value*), np.random.randint(10, 19, *desired y value*), etc..]
plt.hist(data, histtype='stepfilled', bins=[0, 10, etc..])

至于标签,您可以将x刻度与垃圾箱对齐以获得类似以下内容:

#The following will align labels to the center of each bar with bin intervals of 10
plt.xticks([5, 15, etc.. ], ['Label 1', 'Label 2', etc.. ])

This is a very round-about way of doing it but if you want to make a histogram where you already know the bin values but dont have the source data, you can use the np.random.randint function to generate the correct number of values within the range of each bin for the hist function to graph, for example:

import numpy as np
import matplotlib.pyplot as plt

data = [np.random.randint(0, 9, *desired y value*), np.random.randint(10, 19, *desired y value*), etc..]
plt.hist(data, histtype='stepfilled', bins=[0, 10, etc..])

as for labels you can align x ticks with bins to get something like this:

#The following will align labels to the center of each bar with bin intervals of 10
plt.xticks([5, 15, etc.. ], ['Label 1', 'Label 2', etc.. ])

回答 4

这是一个老问题,但是先前的答案都没有解决真正的问题,即问题出在问题本身这一事实。

首先,如果已经计算出概率,即直方图聚合数据可以通过归一化的方式获得,则概率应加起来为1。它们显然没有,这意味着术语或数据有问题。或以询问方式。

其次,提供标签(而不是间隔)的事实通常意味着概率是分类响应变量的-最好使用条形图来绘制直方图(或者对pyplot的hist方法进行一些修改), Shayan Shafiq的答案提供了代码。

但是,请参阅问题1,这些概率是不正确的,在这种情况下使用条形图作为“直方图”将是错误的,因为由于某些原因,它不能告诉单变量分布的故事(也许类别是重叠的,并且观察被计数为多个)时间?),这种情况下不应称为直方图。

根据定义,直方图是单变量分布的图形表示(请参见 https://www.itl.nist.gov/div898/handbook/eda/section3/histogra.htmhttps://en.wikipedia.org/wiki /直方图),并通过绘制各种尺寸的条来创建,这些条表示关注变量的选定类别中的观察次数或观察频率。如果变量以连续刻度进行测量,则这些类别为箱(间隔)。直方图创建过程的重要部分是选择如何对分类变量的响应类别进行分组(或不分组分组),或者如何将可能值的域划分为连续的区间(在其中放置bin边界)类型变量。所有观察结果都应表示出来,并且每个图中只能观察一次。这意味着条形尺寸的总和应等于观察的总数(或宽度可变的情况下其面积,这是一种较不常用的方法)。或者,如果直方图已归一化,则所有概率必须加起来为1。

如果数据本身是作为响应的“概率”列表,即观察值是每个研究对象的(某物)概率值,则最佳答案就是 plt.hist(probability)的可能的装箱选项,并使用已经可用的x标签可疑。

然后,条形图不应用作直方图,而应简单地用作

import matplotlib.pyplot as plt
probability = [0.3602150537634409, 0.42028985507246375, 
  0.373117033603708, 0.36813186813186816, 0.32517482517482516, 
  0.4175257731958763, 0.41025641025641024, 0.39408866995073893, 
  0.4143222506393862, 0.34, 0.391025641025641, 0.3130841121495327, 
  0.35398230088495575]
plt.hist(probability)
plt.show()

结果

在此处输入图片说明

在这种情况下,matplotlib默认带有以下直方图值

(array([1., 1., 1., 1., 1., 2., 0., 2., 0., 4.]),
 array([0.31308411, 0.32380469, 0.33452526, 0.34524584, 0.35596641,
        0.36668698, 0.37740756, 0.38812813, 0.39884871, 0.40956928,
        0.42028986]),
 <a list of 10 Patch objects>)

结果是一个数组元组,第一个数组包含观察计数,即将相对于图的y轴显示的值(它们总计为13,观察总数),第二个数组是x的区间边界-轴。

可以检查它们是否等距分布,

x = plt.hist(probability)[1]
for left, right in zip(x[:-1], x[1:]):
  print(left, right, right-left)

在此处输入图片说明

或者,例如,对于3个bin(我的判断是需要13个观察值),一个将获得此直方图

plt.hist(probability, bins=3)

在此处输入图片说明

情节数据“在酒吧后面”是

在此处输入图片说明

问题的作者需要弄清楚“概率”值列表的含义是什么-“概率”只是响应变量的名称(然后为什么为直方图准备了x标签,这没有任何意义),还是列表值是根据数据计算出的概率(然后它们之和不等于1的事实就没有意义了)。

This is an old question but none of the previous answers has addressed the real issue, i.e. that fact that the problem is with the question itself.

First, if the probabilities have been already calculated, i.e. the histogram aggregated data is available in a normalized way then the probabilities should add up to 1. They obviously do not and that means that something is wrong here, either with terminology or with the data or in the way the question is asked.

Second, the fact that the labels are provided (and not intervals) would normally mean that the probabilities are of categorical response variable – and a use of a bar plot for plotting the histogram is best (or some hacking of the pyplot’s hist method), Shayan Shafiq’s answer provides the code.

However, see issue 1, those probabilities are not correct and using bar plot in this case as “histogram” would be wrong because it does not tell the story of univariate distribution, for some reason (perhaps the classes are overlapping and observations are counted multiple times?) and such plot should not be called a histogram in this case.

Histogram is by definition a graphical representation of the distribution of univariate variable (see https://www.itl.nist.gov/div898/handbook/eda/section3/histogra.htm , https://en.wikipedia.org/wiki/Histogram ) and is created by drawing bars of sizes representing counts or frequencies of observations in selected classes of the variable of interest. If the variable is measured on a continuous scale those classes are bins (intervals). Important part of histogram creation procedure is making a choice of how to group (or keep without grouping) the categories of responses for a categorical variable, or how to split the domain of possible values into intervals (where to put the bin boundaries) for continuous type variable. All observations should be represented, and each one only once in the plot. That means that the sum of the bar sizes should be equal to the total count of observation (or their areas in case of the variable widths, which is a less common approach). Or, if the histogram is normalised then all probabilities must add up to 1.

If the data itself is a list of “probabilities” as a response, i.e. the observations are probability values (of something) for each object of study then the best answer is simply plt.hist(probability) with maybe binning option, and use of x-labels already available is suspicious.

Then bar plot should not be used as histogram but rather simply

import matplotlib.pyplot as plt
probability = [0.3602150537634409, 0.42028985507246375, 
  0.373117033603708, 0.36813186813186816, 0.32517482517482516, 
  0.4175257731958763, 0.41025641025641024, 0.39408866995073893, 
  0.4143222506393862, 0.34, 0.391025641025641, 0.3130841121495327, 
  0.35398230088495575]
plt.hist(probability)
plt.show()

with the results

enter image description here

matplotlib in such case arrives by default with the following histogram values

(array([1., 1., 1., 1., 1., 2., 0., 2., 0., 4.]),
 array([0.31308411, 0.32380469, 0.33452526, 0.34524584, 0.35596641,
        0.36668698, 0.37740756, 0.38812813, 0.39884871, 0.40956928,
        0.42028986]),
 <a list of 10 Patch objects>)

the result is a tuple of arrays, the first array contains observation counts, i.e. what will be shown against the y-axis of the plot (they add up to 13, total number of observations) and the second array are the interval boundaries for x-axis.

One can check they they are equally spaced,

x = plt.hist(probability)[1]
for left, right in zip(x[:-1], x[1:]):
  print(left, right, right-left)

enter image description here

Or, for example for 3 bins (my judgment call for 13 observations) one would get this histogram

plt.hist(probability, bins=3)

enter image description here

with the plot data “behind the bars” being

enter image description here

The author of the question needs to clarify what is the meaning of the “probability” list of values – is the “probability” just a name of the response variable (then why are there x-labels ready for the histogram, it makes no sense), or are the list values the probabilities calculated from the data (then the fact they do not add up to 1 makes no sense).


更改matplotlib中图的轴,刻度和标签的颜色

问题:更改matplotlib中图的轴,刻度和标签的颜色

我想更改轴的颜色,以及我使用matplotlib和PyQt所做的绘图的刻度和值标签。

有任何想法吗?

I’d like to Change the color of the axis, as well as ticks and value-labels for a plot I did using matplotlib an PyQt.

Any ideas?


回答 0

举一个快速的例子(使用比可能重复的问题稍微干净的方法):

import matplotlib.pyplot as plt

fig = plt.figure()
ax = fig.add_subplot(111)

ax.plot(range(10))
ax.set_xlabel('X-axis')
ax.set_ylabel('Y-axis')

ax.spines['bottom'].set_color('red')
ax.spines['top'].set_color('red')
ax.xaxis.label.set_color('red')
ax.tick_params(axis='x', colors='red')

plt.show()

替代文字

As a quick example (using a slightly cleaner method than the potentially duplicate question):

import matplotlib.pyplot as plt

fig = plt.figure()
ax = fig.add_subplot(111)

ax.plot(range(10))
ax.set_xlabel('X-axis')
ax.set_ylabel('Y-axis')

ax.spines['bottom'].set_color('red')
ax.spines['top'].set_color('red')
ax.xaxis.label.set_color('red')
ax.tick_params(axis='x', colors='red')

plt.show()

alt text


回答 1

如果您要修改多个图形或子图,则使用matplotlib上下文管理器来更改颜色可能会有所帮助,而不是分别更改每个颜色或子图。上下文管理器允许您仅针对紧随其后的缩进代码临时更改rc参数,但不影响全局rc参数。

此代码段产生两个图形,第一个图形具有修改的轴,刻度线和刻度标签颜色,第二个图形具有默认的rc参数。

import matplotlib.pyplot as plt
with plt.rc_context({'axes.edgecolor':'orange', 'xtick.color':'red', 'ytick.color':'green', 'figure.facecolor':'white'}):
    # Temporary rc parameters in effect
    fig, (ax1, ax2) = plt.subplots(1,2)
    ax1.plot(range(10))
    ax2.plot(range(10))
# Back to default rc parameters
fig, ax = plt.subplots()
ax.plot(range(10))

在此处输入图片说明

在此处输入图片说明

您可以键入plt.rcParams以查看所有可用的rc参数,并使用列表推导来搜索关键字:

# Search for all parameters containing the word 'color'
[(param, value) for param, value in plt.rcParams.items() if 'color' in param]

If you have several figures or subplots that you want to modify, it can be helpful to use the matplotlib context manager to change the color, instead of changing each one individually. The context manager allows you to temporarily change the rc parameters only for the immediately following indented code, but does not affect the global rc parameters.

This snippet yields two figures, the first one with modified colors for the axis, ticks and ticklabels, and the second one with the default rc parameters.

import matplotlib.pyplot as plt
with plt.rc_context({'axes.edgecolor':'orange', 'xtick.color':'red', 'ytick.color':'green', 'figure.facecolor':'white'}):
    # Temporary rc parameters in effect
    fig, (ax1, ax2) = plt.subplots(1,2)
    ax1.plot(range(10))
    ax2.plot(range(10))
# Back to default rc parameters
fig, ax = plt.subplots()
ax.plot(range(10))

enter image description here

enter image description here

You can type plt.rcParams to view all available rc parameters, and use list comprehension to search for keywords:

# Search for all parameters containing the word 'color'
[(param, value) for param, value in plt.rcParams.items() if 'color' in param]

回答 2

在以前的贡献者的激励下,这是三个轴的示例。

import matplotlib.pyplot as plt

x_values1=[1,2,3,4,5]
y_values1=[1,2,2,4,1]

x_values2=[-1000,-800,-600,-400,-200]
y_values2=[10,20,39,40,50]

x_values3=[150,200,250,300,350]
y_values3=[-10,-20,-30,-40,-50]


fig=plt.figure()
ax=fig.add_subplot(111, label="1")
ax2=fig.add_subplot(111, label="2", frame_on=False)
ax3=fig.add_subplot(111, label="3", frame_on=False)

ax.plot(x_values1, y_values1, color="C0")
ax.set_xlabel("x label 1", color="C0")
ax.set_ylabel("y label 1", color="C0")
ax.tick_params(axis='x', colors="C0")
ax.tick_params(axis='y', colors="C0")

ax2.scatter(x_values2, y_values2, color="C1")
ax2.set_xlabel('x label 2', color="C1") 
ax2.xaxis.set_label_position('bottom') # set the position of the second x-axis to bottom
ax2.spines['bottom'].set_position(('outward', 36))
ax2.tick_params(axis='x', colors="C1")
ax2.set_ylabel('y label 2', color="C1")       
ax2.yaxis.tick_right()
ax2.yaxis.set_label_position('right') 
ax2.tick_params(axis='y', colors="C1")

ax3.plot(x_values3, y_values3, color="C2")
ax3.set_xlabel('x label 3', color='C2')
ax3.xaxis.set_label_position('bottom')
ax3.spines['bottom'].set_position(('outward', 72))
ax3.tick_params(axis='x', colors='C2')
ax3.set_ylabel('y label 3', color='C2')
ax3.yaxis.tick_right()
ax3.yaxis.set_label_position('right') 
ax3.spines['right'].set_position(('outward', 36))
ax3.tick_params(axis='y', colors='C2')


plt.show()

motivated by previous contributors, this is an example of three axes.

import matplotlib.pyplot as plt

x_values1=[1,2,3,4,5]
y_values1=[1,2,2,4,1]

x_values2=[-1000,-800,-600,-400,-200]
y_values2=[10,20,39,40,50]

x_values3=[150,200,250,300,350]
y_values3=[-10,-20,-30,-40,-50]


fig=plt.figure()
ax=fig.add_subplot(111, label="1")
ax2=fig.add_subplot(111, label="2", frame_on=False)
ax3=fig.add_subplot(111, label="3", frame_on=False)

ax.plot(x_values1, y_values1, color="C0")
ax.set_xlabel("x label 1", color="C0")
ax.set_ylabel("y label 1", color="C0")
ax.tick_params(axis='x', colors="C0")
ax.tick_params(axis='y', colors="C0")

ax2.scatter(x_values2, y_values2, color="C1")
ax2.set_xlabel('x label 2', color="C1") 
ax2.xaxis.set_label_position('bottom') # set the position of the second x-axis to bottom
ax2.spines['bottom'].set_position(('outward', 36))
ax2.tick_params(axis='x', colors="C1")
ax2.set_ylabel('y label 2', color="C1")       
ax2.yaxis.tick_right()
ax2.yaxis.set_label_position('right') 
ax2.tick_params(axis='y', colors="C1")

ax3.plot(x_values3, y_values3, color="C2")
ax3.set_xlabel('x label 3', color='C2')
ax3.xaxis.set_label_position('bottom')
ax3.spines['bottom'].set_position(('outward', 72))
ax3.tick_params(axis='x', colors='C2')
ax3.set_ylabel('y label 3', color='C2')
ax3.yaxis.tick_right()
ax3.yaxis.set_label_position('right') 
ax3.spines['right'].set_position(('outward', 36))
ax3.tick_params(axis='y', colors='C2')


plt.show()