标签归档:matplotlib

10行代码绘制漂亮金融K线图,Mplfinance 这个神器你不可错过

近期发现许多小伙伴有绘制K线图的需求,甚至有些同学没有用第三方模块自己写代码绘制图表,其实这完全是重复性工作,网上有许多已经成熟的K线图绘制方案,比如我们今天要讲的 Mplfinance.

Mplfinance 其实是 Matplotlib 组织开源项目的一部分。相对于Matplotlib,Mplfinance这个处于金融行业的垂直领域的模块的关注度确实是少了一些,以至于很多朋友都不知道它的存在,实际上它非常实用且好用。

1.准备

开始之前,你要确保Python和pip已经成功安装在电脑上,如果没有,请访问这篇文章:超详细Python安装指南 进行安装。

(可选1) 如果你用Python的目的是数据分析,可以直接安装Anaconda:Python数据分析与挖掘好帮手—Anaconda,它内置了Python和pip.

(可选2) 此外,推荐大家用VSCode编辑器来编写小型Python项目:Python 编程的最好搭档—VSCode 详细指南

Windows环境下打开Cmd(开始—运行—CMD),苹果系统环境下请打开Terminal(command+空格输入Terminal),输入命令安装依赖:

pip install --upgrade mplfinance

2.Mplfinance 基本使用

我们以沪深300分钟线为例,使用mplfinance绘制各类金融图形。

首先看看数据结构:

import pandas as pd
mins = pd.read_csv('sh300_1min.csv',index_col=0,parse_dates=True)
print(mins)

结构如下:

                       day      open      high       low     close     volume
0      2022-03-07 10:47:00  4406.223  4406.352  4405.662  4405.922   54345400
1      2022-03-07 10:48:00  4406.172  4406.175  4403.834  4403.918   70803100
2      2022-03-07 10:49:00  4403.333  4403.333  4402.235  4402.340   49632500
3      2022-03-07 10:50:00  4402.330  4402.519  4401.838  4402.519   48159200

我们用于mplfinance的数据必须是 Pandas DataFrame. 字段则按需提供,至少要有时间字段和一列数据。另外原始数据如果是其他的数据类型,你必须得先转成DataFrame格式。

此外,时间字段必须转为DatetimeIndex:

# 公众号:二七阿尔量化
import pandas as pd
import mplfinance as mpf
mins = pd.read_csv('sh300_1min.csv',index_col=0,parse_dates=True)
mins["day"] = pd.to_datetime(mins["day"])
mins = mins.set_index("day")
mins.index.name = 'Time'
print(mins)

效果如下:

                         open      high       low     close     volume
Time
2022-03-07 10:47:00  4406.223  4406.352  4405.662  4405.922   54345400
2022-03-07 10:48:00  4406.172  4406.175  4403.834  4403.918   70803100
2022-03-07 10:49:00  4403.333  4403.333  4402.235  4402.340   49632500
2022-03-07 10:50:00  4402.330  4402.519  4401.838  4402.519   48159200

准备完成后就可以绘制图表了:

# 公众号:二七阿尔量化
import pandas as pd
import mplfinance as mpf
mins = pd.read_csv('sh300_1min.csv',index_col=0,parse_dates=True)
mins["day"] = pd.to_datetime(mins["day"])
mins = mins.set_index("day")
mins.index.name = 'Time'

# 绘制默认图像(美国线)
mpf.plot(mins)

绘制蜡烛图(K线图),为了避免图表过大,我这里只取了240条K线:

# 公众号:二七阿尔量化
import pandas as pd
import mplfinance as mpf
mins = pd.read_csv('sh300_1min.csv',index_col=0,parse_dates=True)
mins["day"] = pd.to_datetime(mins["day"])
mins = mins.set_index("day")
mins.index.name = 'Time'

candle_chart = mins.tail(240)
mpf.plot(candle_chart, type='candle')

黑白颜色太单调了,我们可以换成“雅虎”配色:

mpf.plot(candle_chart, type='candle', style='yahoo')

绘制线型图:

# 公众号:二七阿尔量化
import pandas as pd
import mplfinance as mpf
mins = pd.read_csv('sh300_1min.csv',index_col=0,parse_dates=True)
mins["day"] = pd.to_datetime(mins["day"])
mins = mins.set_index("day")
mins.index.name = 'Time'
mpf.plot(mins, type='line')

除了美国线、蜡烛图(K线)、线型图外,mplfinance还支持 renko、pnf 等图形。有兴趣的同学可以改个type看看效果:

3.添加技术指标

绘制简单移动平均线MA5,我们只需要多加一个参数:

# 公众号:二七阿尔量化
import pandas as pd
import mplfinance as mpf
mins = pd.read_csv('sh300_1min.csv',index_col=0,parse_dates=True)
mins["day"] = pd.to_datetime(mins["day"])
mins = mins.set_index("day")
mins.index.name = 'Time'
candle_chart = mins.tail(240)
mpf.plot(candle_chart, type='candle', mav=5)

如果你需要多条移动平均线,只需要将mav改为元组参数,传入你需要的周期参数:

如果你还需要显示成交量(volume), mplfinance 也能实现:

# 公众号:二七阿尔量化
import pandas as pd
import mplfinance as mpf
mins = pd.read_csv('sh300_1min.csv',index_col=0,parse_dates=True)
mins["day"] = pd.to_datetime(mins["day"])
mins = mins.set_index("day")
mins.index.name = 'Time'
candle_chart = mins.tail(240)
mpf.plot(candle_chart, type='candle', mav=(5, 10, 20), volume=True)

如果你还想给蜡烛上色、想更改线条颜色、想增加其他指标,请看第三部分高级使用。

3.高级使用

上色是非常简单的,正如我们之前换成雅虎配色一样,你只需要添加style参数即可换成我们传统的技术指标颜色。但如果你想自定义颜色也是可以做到的,这里我将前120根柱子设置为蓝黄相间,后120根柱子保留原形:

# 公众号:二七阿尔量化
import pandas as pd
import mplfinance as mpf
mins = pd.read_csv('sh300_1min.csv',index_col=0,parse_dates=True)
mins["day"] = pd.to_datetime(mins["day"])
mins = mins.set_index("day")
mins.index.name = 'Time'
candle_chart = mins.tail(240)
mco = ['yellow','blue'] * 60 + [None] * 120
mpf.plot(candle_chart, volume=True, style='yahoo', type='candle', marketcolor_overrides=mco)

效果如下:

有些同学还希望能够绘制自己的技术指标,mplfinance也可以做到:

# 公众号:二七阿尔量化
# https://github.com/matplotlib/mplfinance/blob/master/examples/mpf_animation_macd.py#L28

import pandas as pd
import mplfinance as mpf
import matplotlib.animation as animation

mins = pd.read_csv('sh300_1min.csv',index_col=0,parse_dates=True)
mins["day"] = pd.to_datetime(mins["day"])
mins = mins.set_index("day")
mins.index.name = 'Time'
candle_chart = mins.tail(240)

df = candle_chart

exp12     = df['close'].ewm(span=12, adjust=False).mean()
exp26     = df['close'].ewm(span=26, adjust=False).mean()
macd      = exp12 - exp26
signal    = macd.ewm(span=9, adjust=False).mean()
histogram = macd - signal

apds = [mpf.make_addplot(exp12,color='lime'),
        mpf.make_addplot(exp26,color='c'),
        mpf.make_addplot(histogram,type='bar',width=0.7,panel=1,
                         color='dimgray',alpha=1,secondary_y=False),
        mpf.make_addplot(macd,panel=1,color='fuchsia',secondary_y=True),
        mpf.make_addplot(signal,panel=1,color='b',secondary_y=True),
       ]

s = mpf.make_mpf_style(base_mpf_style='classic',rc={'figure.facecolor':'lightgray'})

fig, axes = mpf.plot(df,type='candle',addplot=apds,figscale=1.5,figratio=(7,5),title='\n\nMACD',
                     style=s,volume=True,volume_panel=2,panel_ratios=(6,3,2),returnfig=True)

mpf.show()

mpf.make_addplot 支持添加任意图形到任意panel上,panel参数默认为0,如果设为1则将图形添加到第二个图上,color参数能设置图形颜色,secondary_y 能将图形的值设置到y轴上。效果如下:

此外,如果你希望能动态看到整个绘制过程,增加个animation即可:

# 公众号:二七阿尔量化
import pandas as pd
import mplfinance as mpf
import matplotlib.animation as animation

mins = pd.read_csv('sh300_1min.csv',index_col=0,parse_dates=True)
mins["day"] = pd.to_datetime(mins["day"])
mins = mins.set_index("day")
mins.index.name = 'Time'
candle_chart = mins.tail(240)

df = candle_chart

exp12     = df['close'].ewm(span=12, adjust=False).mean()
exp26     = df['close'].ewm(span=26, adjust=False).mean()
macd      = exp12 - exp26
signal    = macd.ewm(span=9, adjust=False).mean()
histogram = macd - signal

apds = [mpf.make_addplot(exp12,color='lime'),
        mpf.make_addplot(exp26,color='c'),
        mpf.make_addplot(histogram,type='bar',width=0.7,panel=1,
                         color='dimgray',alpha=1,secondary_y=False),
        mpf.make_addplot(macd,panel=1,color='fuchsia',secondary_y=True),
        mpf.make_addplot(signal,panel=1,color='b',secondary_y=True),
       ]

s = mpf.make_mpf_style(base_mpf_style='classic',rc={'figure.facecolor':'lightgray'})

fig, axes = mpf.plot(df,type='candle',addplot=apds,figscale=1.5,figratio=(7,5),title='\n\nMACD',
                     style=s,volume=True,volume_panel=2,panel_ratios=(6,3,2),returnfig=True)

mpf.show()

ax_main = axes[0]
ax_emav = ax_main
ax_hisg = axes[2]
ax_macd = axes[3]
ax_sign = ax_macd
ax_volu = axes[4]


def animate(ival):
    if (20+ival) > len(df):
        print('no more data to plot')
        ani.event_source.interval *= 3
        if ani.event_source.interval > 12000:
            exit()
        return
    data = df.iloc[0:(30+ival)]
    exp12     = data['close'].ewm(span=12, adjust=False).mean()
    exp26     = data['close'].ewm(span=26, adjust=False).mean()
    macd      = exp12 - exp26
    signal    = macd.ewm(span=9, adjust=False).mean()
    histogram = macd - signal
    apds = [mpf.make_addplot(exp12,color='lime',ax=ax_emav),
            mpf.make_addplot(exp26,color='c',ax=ax_emav),
            mpf.make_addplot(histogram,type='bar',width=0.7,
                             color='dimgray',alpha=1,ax=ax_hisg),
            mpf.make_addplot(macd,color='fuchsia',ax=ax_macd),
            mpf.make_addplot(signal,color='b',ax=ax_sign),
           ]

    for ax in axes:
        ax.clear()
    mpf.plot(data,type='candle',addplot=apds,ax=ax_main,volume=ax_volu)

ani = animation.FuncAnimation(fig,animate,interval=100)

mpf.show()

还有许多更有趣的玩法,你可以阅读mplfinance的examples学习更多的使用技巧:

https://github.com/matplotlib/mplfinance/tree/master/examples

本文的全部代码和数据包括mplfinance的examples都可以在【二七阿尔量化】公众号后台回复:mplfinance 下载。

我们的文章到此就结束啦,如果你喜欢今天的 Python 教程,请持续关注Python实用宝典。

有任何问题,可以在公众号后台回复:加群,回答相应验证信息,进入互助群询问。

原创不易,希望你能在下面点个赞和在看支持我继续创作,谢谢!

给作者打赏,选择打赏金额
¥1¥5¥10¥20¥50¥100¥200 自定义

​Python实用宝典 ( pythondict.com )
不只是一个宝典
欢迎关注公众号:Python实用宝典

matplotlib中的日期刻度和旋转

问题:matplotlib中的日期刻度和旋转

我在尝试在matplotlib中旋转日期刻度时遇到问题。下面是一个小示例程序。如果我尝试最后旋转刻度线,则刻度线不会旋转。如果我尝试如注释“ crashes”下所示旋转刻度线,则matplot lib崩溃。

仅当x值为日期时,才会发生这种情况。如果我在的调用dates中将变量替换tavail_plot,则该xticks(rotation=70)调用在内部正常运行avail_plot

有任何想法吗?

import numpy as np
import matplotlib.pyplot as plt
import datetime as dt

def avail_plot(ax, x, y, label, lcolor):
    ax.plot(x,y,'b')
    ax.set_ylabel(label, rotation='horizontal', color=lcolor)
    ax.get_yaxis().set_ticks([])

    #crashes
    #plt.xticks(rotation=70)

    ax2 = ax.twinx()
    ax2.plot(x, [1 for a in y], 'b')
    ax2.get_yaxis().set_ticks([])
    ax2.set_ylabel('testing')

f, axs = plt.subplots(2, sharex=True, sharey=True)
t = np.arange(0.01, 5, 1)
s1 = np.exp(t)
start = dt.datetime.now()
dates=[]
for val in t:
    next_val = start + dt.timedelta(0,val)
    dates.append(next_val)
    start = next_val

avail_plot(axs[0], dates, s1, 'testing', 'green')
avail_plot(axs[1], dates, s1, 'testing2', 'red')
plt.subplots_adjust(hspace=0, bottom=0.3)
plt.yticks([0.5,],("",""))
#doesn't crash, but does not rotate the xticks
#plt.xticks(rotation=70)
plt.show()

I am having an issue trying to get my date ticks rotated in matplotlib. A small sample program is below. If I try to rotate the ticks at the end, the ticks do not get rotated. If I try to rotate the ticks as shown under the comment ‘crashes’, then matplot lib crashes.

This only happens if the x-values are dates. If I replaces the variable dates with the variable t in the call to avail_plot, the xticks(rotation=70) call works just fine inside avail_plot.

Any ideas?

import numpy as np
import matplotlib.pyplot as plt
import datetime as dt

def avail_plot(ax, x, y, label, lcolor):
    ax.plot(x,y,'b')
    ax.set_ylabel(label, rotation='horizontal', color=lcolor)
    ax.get_yaxis().set_ticks([])

    #crashes
    #plt.xticks(rotation=70)

    ax2 = ax.twinx()
    ax2.plot(x, [1 for a in y], 'b')
    ax2.get_yaxis().set_ticks([])
    ax2.set_ylabel('testing')

f, axs = plt.subplots(2, sharex=True, sharey=True)
t = np.arange(0.01, 5, 1)
s1 = np.exp(t)
start = dt.datetime.now()
dates=[]
for val in t:
    next_val = start + dt.timedelta(0,val)
    dates.append(next_val)
    start = next_val

avail_plot(axs[0], dates, s1, 'testing', 'green')
avail_plot(axs[1], dates, s1, 'testing2', 'red')
plt.subplots_adjust(hspace=0, bottom=0.3)
plt.yticks([0.5,],("",""))
#doesn't crash, but does not rotate the xticks
#plt.xticks(rotation=70)
plt.show()

回答 0

如果您喜欢非面向对象的方法,请在两个调用之前移至plt.xticks(rotation=70)右侧,例如avail_plot

plt.xticks(rotation=70)
avail_plot(axs[0], dates, s1, 'testing', 'green')
avail_plot(axs[1], dates, s1, 'testing2', 'red')

这将在设置标签之前设置旋转属性。由于这里有两个轴,因此plt.xticks在绘制了两个图后会感到困惑。而此时点plt.xticks什么都不做,plt.gca()没有给你想要修改的轴等plt.xticks作用于当前坐标,是行不通的。

对于不使用的面向对象方法plt.xticks,可以使用

plt.setp( axs[1].xaxis.get_majorticklabels(), rotation=70 )

两次avail_plot通话之后。这样可以专门设置正确轴上的旋转。

If you prefer a non-object-oriented approach, move plt.xticks(rotation=70) to right before the two avail_plot calls, eg

plt.xticks(rotation=70)
avail_plot(axs[0], dates, s1, 'testing', 'green')
avail_plot(axs[1], dates, s1, 'testing2', 'red')

This sets the rotation property before setting up the labels. Since you have two axes here, plt.xticks gets confused after you’ve made the two plots. At the point when plt.xticks doesn’t do anything, plt.gca() does not give you the axes you want to modify, and so plt.xticks, which acts on the current axes, is not going to work.

For an object-oriented approach not using plt.xticks, you can use

plt.setp( axs[1].xaxis.get_majorticklabels(), rotation=70 )

after the two avail_plot calls. This sets the rotation on the correct axes specifically.


回答 1

解决方案适用于Matplotlib 2.1+

存在tick_params可以更改刻度属性的轴方法。它也作为轴方法存在set_tick_params

ax.tick_params(axis='x', rotation=45)

要么

ax.xaxis.set_tick_params(rotation=45)

附带说明一下,当前解决方案通过使用command将有状态接口(使用pyplot)与面向对象的接口混合在一起plt.xticks(rotation=70)。由于问题中的代码使用面向对象的方法,因此最好始终坚持使用该方法。该解决方案确实提供了一个很好的显式解决方案plt.setp( axs[1].xaxis.get_majorticklabels(), rotation=70 )

Solution works for matplotlib 2.1+

There exists an axes method tick_params that can change tick properties. It also exists as an axis method as set_tick_params

ax.tick_params(axis='x', rotation=45)

Or

ax.xaxis.set_tick_params(rotation=45)

As a side note, the current solution mixes the stateful interface (using pyplot) with the object-oriented interface by using the command plt.xticks(rotation=70). Since the code in the question uses the object-oriented approach, it’s best to stick to that approach throughout. The solution does give a good explicit solution with plt.setp( axs[1].xaxis.get_majorticklabels(), rotation=70 )


回答 2

一个简单的解决方案是使用

fig.autofmt_xdate()

该命令自动旋转xaxis标签并调整其位置。默认值为旋转角度30°和水平对齐“向右”。但是可以在函数调用中更改它们

fig.autofmt_xdate(bottom=0.2, rotation=30, ha='right')

附加bottom参数等效于setting plt.subplots_adjust(bottom=bottom),它允许将底部轴的padding设置为更大的值,以承载旋转的ticklabel。

因此,基本上,这里您具有所有需要的设置,只需一个命令即可拥有一个漂亮的日期轴。

在matplotlib页面上可以找到一个很好的例子

An easy solution which avoids looping over the ticklabes is to just use

fig.autofmt_xdate()

This command automatically rotates the xaxis labels and adjusts their position. The default values are a rotation angle 30° and horizontal alignment “right”. But they can be changed in the function call

fig.autofmt_xdate(bottom=0.2, rotation=30, ha='right')

The additional bottom argument is equivalent to setting plt.subplots_adjust(bottom=bottom), which allows to set the bottom axes padding to a larger value to host the rotated ticklabels.

So basically here you have all the settings you need to have a nice date axis in a single command.

A good example can be found on the matplotlib page.


回答 3

申请的另一种方式horizontalalignment,并rotation给每个刻度标签做for了你要更改的刻度标记循环:

import numpy as np
import matplotlib.pyplot as plt
import datetime as dt

now = dt.datetime.now()
hours = [now + dt.timedelta(minutes=x) for x in range(0,24*60,10)]
days = [now + dt.timedelta(days=x) for x in np.arange(0,30,1/4.)]
hours_value = np.random.random(len(hours))
days_value = np.random.random(len(days))

fig, axs = plt.subplots(2)
fig.subplots_adjust(hspace=0.75)
axs[0].plot(hours,hours_value)
axs[1].plot(days,days_value)

for label in axs[0].get_xmajorticklabels() + axs[1].get_xmajorticklabels():
    label.set_rotation(30)
    label.set_horizontalalignment("right")

这是一个示例,如果您想控制主要和次要刻度线的位置:

import numpy as np
import matplotlib.pyplot as plt
import datetime as dt

fig, axs = plt.subplots(2)
fig.subplots_adjust(hspace=0.75)
now = dt.datetime.now()
hours = [now + dt.timedelta(minutes=x) for x in range(0,24*60,10)]
days = [now + dt.timedelta(days=x) for x in np.arange(0,30,1/4.)]

axs[0].plot(hours,np.random.random(len(hours)))
x_major_lct = mpl.dates.AutoDateLocator(minticks=2,maxticks=10, interval_multiples=True)
x_minor_lct = matplotlib.dates.HourLocator(byhour = range(0,25,1))
x_fmt = matplotlib.dates.AutoDateFormatter(x_major_lct)
axs[0].xaxis.set_major_locator(x_major_lct)
axs[0].xaxis.set_minor_locator(x_minor_lct)
axs[0].xaxis.set_major_formatter(x_fmt)
axs[0].set_xlabel("minor ticks set to every hour, major ticks start with 00:00")

axs[1].plot(days,np.random.random(len(days)))
x_major_lct = mpl.dates.AutoDateLocator(minticks=2,maxticks=10, interval_multiples=True)
x_minor_lct = matplotlib.dates.DayLocator(bymonthday = range(0,32,1))
x_fmt = matplotlib.dates.AutoDateFormatter(x_major_lct)
axs[1].xaxis.set_major_locator(x_major_lct)
axs[1].xaxis.set_minor_locator(x_minor_lct)
axs[1].xaxis.set_major_formatter(x_fmt)
axs[1].set_xlabel("minor ticks set to every day, major ticks show first day of month")
for label in axs[0].get_xmajorticklabels() + axs[1].get_xmajorticklabels():
    label.set_rotation(30)
    label.set_horizontalalignment("right")

Another way to applyhorizontalalignment and rotation to each tick label is doing a for loop over the tick labels you want to change:

import numpy as np
import matplotlib.pyplot as plt
import datetime as dt

now = dt.datetime.now()
hours = [now + dt.timedelta(minutes=x) for x in range(0,24*60,10)]
days = [now + dt.timedelta(days=x) for x in np.arange(0,30,1/4.)]
hours_value = np.random.random(len(hours))
days_value = np.random.random(len(days))

fig, axs = plt.subplots(2)
fig.subplots_adjust(hspace=0.75)
axs[0].plot(hours,hours_value)
axs[1].plot(days,days_value)

for label in axs[0].get_xmajorticklabels() + axs[1].get_xmajorticklabels():
    label.set_rotation(30)
    label.set_horizontalalignment("right")

And here is an example if you want to control the location of major and minor ticks:

import numpy as np
import matplotlib.pyplot as plt
import datetime as dt

fig, axs = plt.subplots(2)
fig.subplots_adjust(hspace=0.75)
now = dt.datetime.now()
hours = [now + dt.timedelta(minutes=x) for x in range(0,24*60,10)]
days = [now + dt.timedelta(days=x) for x in np.arange(0,30,1/4.)]

axs[0].plot(hours,np.random.random(len(hours)))
x_major_lct = mpl.dates.AutoDateLocator(minticks=2,maxticks=10, interval_multiples=True)
x_minor_lct = matplotlib.dates.HourLocator(byhour = range(0,25,1))
x_fmt = matplotlib.dates.AutoDateFormatter(x_major_lct)
axs[0].xaxis.set_major_locator(x_major_lct)
axs[0].xaxis.set_minor_locator(x_minor_lct)
axs[0].xaxis.set_major_formatter(x_fmt)
axs[0].set_xlabel("minor ticks set to every hour, major ticks start with 00:00")

axs[1].plot(days,np.random.random(len(days)))
x_major_lct = mpl.dates.AutoDateLocator(minticks=2,maxticks=10, interval_multiples=True)
x_minor_lct = matplotlib.dates.DayLocator(bymonthday = range(0,32,1))
x_fmt = matplotlib.dates.AutoDateFormatter(x_major_lct)
axs[1].xaxis.set_major_locator(x_major_lct)
axs[1].xaxis.set_minor_locator(x_minor_lct)
axs[1].xaxis.set_major_formatter(x_fmt)
axs[1].set_xlabel("minor ticks set to every day, major ticks show first day of month")
for label in axs[0].get_xmajorticklabels() + axs[1].get_xmajorticklabels():
    label.set_rotation(30)
    label.set_horizontalalignment("right")


回答 4

只需使用

ax.set_xticklabels(label_list, rotation=45)

Simply use

ax.set_xticklabels(label_list, rotation=45)

在Matplotlib中为线上的单个点设置标记

问题:在Matplotlib中为线上的单个点设置标记

我已经使用Matplotlib在图形上绘制线条。现在,我想为线上的各个点设置样式,特别是标记。我该怎么做呢?

为了澄清我的问题,我希望能够为一行中的单个标记设置样式,而不是为该行上的每个标记设置样式。

I have used Matplotlib to plot lines on a figure. Now I would now like to set the style, specifically the marker, for individual points on the line. How do I do this?

To clarify my question, I want to be able to set the style for individual markers on a line, not every marker on said line.


回答 0

在调用中指定关键字args linestyle和/或。markerplot

例如,使用虚线和蓝色圆圈标记:

plt.plot(range(10), linestyle='--', marker='o', color='b')

相同内容的快捷方式调用:

plt.plot(range(10), '--bo')

这是可能的线条和标记样式的列表:

================    ===============================
character           description
================    ===============================
   -                solid line style
   --               dashed line style
   -.               dash-dot line style
   :                dotted line style
   .                point marker
   ,                pixel marker
   o                circle marker
   v                triangle_down marker
   ^                triangle_up marker
   <                triangle_left marker
   >                triangle_right marker
   1                tri_down marker
   2                tri_up marker
   3                tri_left marker
   4                tri_right marker
   s                square marker
   p                pentagon marker
   *                star marker
   h                hexagon1 marker
   H                hexagon2 marker
   +                plus marker
   x                x marker
   D                diamond marker
   d                thin_diamond marker
   |                vline marker
   _                hline marker
================    ===============================

编辑: 以标记点的任意子集为例,如注释中所要求:

import numpy as np
import matplotlib.pyplot as plt

xs = np.linspace(-np.pi, np.pi, 30)
ys = np.sin(xs)
markers_on = [12, 17, 18, 19]
plt.plot(xs, ys, '-gD', markevery=markers_on)
plt.show()

markevery由于此功能分支的合并,从1.4+开始,使用kwarg的最后一个示例是可能的。如果您坚持使用较旧版本的matplotlib,则仍可以通过在散点图上覆盖散点图来获得结果。有关更多详细信息,请参见编辑历史记录

Specify the keyword args linestyle and/or marker in your call to plot.

For example, using a dashed line and blue circle markers:

plt.plot(range(10), linestyle='--', marker='o', color='b')

A shortcut call for the same thing:

plt.plot(range(10), '--bo')

Here is a list of the possible line and marker styles:

================    ===============================
character           description
================    ===============================
   -                solid line style
   --               dashed line style
   -.               dash-dot line style
   :                dotted line style
   .                point marker
   ,                pixel marker
   o                circle marker
   v                triangle_down marker
   ^                triangle_up marker
   <                triangle_left marker
   >                triangle_right marker
   1                tri_down marker
   2                tri_up marker
   3                tri_left marker
   4                tri_right marker
   s                square marker
   p                pentagon marker
   *                star marker
   h                hexagon1 marker
   H                hexagon2 marker
   +                plus marker
   x                x marker
   D                diamond marker
   d                thin_diamond marker
   |                vline marker
   _                hline marker
================    ===============================

edit: with an example of marking an arbitrary subset of points, as requested in the comments:

import numpy as np
import matplotlib.pyplot as plt

xs = np.linspace(-np.pi, np.pi, 30)
ys = np.sin(xs)
markers_on = [12, 17, 18, 19]
plt.plot(xs, ys, '-gD', markevery=markers_on)
plt.show()

This last example using the markevery kwarg is possible in since 1.4+, due to the merge of this feature branch. If you are stuck on an older version of matplotlib, you can still achieve the result by overlaying a scatterplot on the line plot. See the edit history for more details.


回答 1

有一张图片显示所有标记的名称和描述,希望对您有帮助。

import matplotlib.pylab as plt
markers=['.',',','o','v','^','<','>','1','2','3','4','8','s','p','P','*','h','H','+','x','X','D','d','|','_']
descriptions=['point', 'pixel', 'circle', 'triangle_down', 'triangle_up','triangle_left', 'triangle_right', 'tri_down', 'tri_up', 'tri_left','tri_right', 'octagon', 'square', 'pentagon', 'plus (filled)','star', 'hexagon1', 'hexagon2', 'plus', 'x', 'x (filled)','diamond', 'thin_diamond', 'vline', 'hline']
x=[]
y=[]
for i in range(5):
    for j in range(5):
        x.append(i)
        y.append(j)
plt.figure()
for i,j,m,l in zip(x,y,markers,descriptions):
    plt.scatter(i,j,marker=m)
    plt.text(i-0.15,j+0.15,s=m+' : '+l)
plt.axis([-0.1,4.8,-0.1,4.5])
plt.tight_layout()
plt.axis('off')
plt.show()  

There is a picture show all markers’ name and description, i hope it will help you.

import matplotlib.pylab as plt
markers=['.',',','o','v','^','<','>','1','2','3','4','8','s','p','P','*','h','H','+','x','X','D','d','|','_']
descriptions=['point', 'pixel', 'circle', 'triangle_down', 'triangle_up','triangle_left', 'triangle_right', 'tri_down', 'tri_up', 'tri_left','tri_right', 'octagon', 'square', 'pentagon', 'plus (filled)','star', 'hexagon1', 'hexagon2', 'plus', 'x', 'x (filled)','diamond', 'thin_diamond', 'vline', 'hline']
x=[]
y=[]
for i in range(5):
    for j in range(5):
        x.append(i)
        y.append(j)
plt.figure()
for i,j,m,l in zip(x,y,markers,descriptions):
    plt.scatter(i,j,marker=m)
    plt.text(i-0.15,j+0.15,s=m+' : '+l)
plt.axis([-0.1,4.8,-0.1,4.5])
plt.tight_layout()
plt.axis('off')
plt.show()  


回答 2

供将来参考- Line2D艺术家返回的艺术家plot()还有一种set_markevery()方法,允许您仅在某些点上设置标记-请参见https://matplotlib.org/api/_as_gen/matplotlib.lines.Line2D.html#matplotlib.lines.Line2D。 set_markevery

For future reference – the Line2D artist returned by plot() also has a set_markevery() method which allows you to only set markers on certain points – see https://matplotlib.org/api/_as_gen/matplotlib.lines.Line2D.html#matplotlib.lines.Line2D.set_markevery


回答 3

更改特定点标记形状,大小的一个简单技巧是:首先将其与所有其他数据一起绘制,然后仅对该点(或一组点,如果要更改多个点的样式)再绘制一个图。假设我们要更改第二点的标记形状:

x = [1,2,3,4,5]
y = [2,1,3,6,7]

plt.plot(x, y, "-o")
x0 = [2]
y0 = [1]
plt.plot(x0, y0, "s")

plt.show()

结果是: 用多个标记绘制

A simple trick to change a particular point marker shape, size… is to first plot it with all the other data then plot one more plot only with that point(or set of points if you want to change the style of multiple points). Suppose we want to change the marker shape of second point:

x = [1,2,3,4,5]
y = [2,1,3,6,7]

plt.plot(x, y, "-o")
x0 = [2]
y0 = [1]
plt.plot(x0, y0, "s")

plt.show()

Result is: Plot with multiple markers


Matplotlib(pyplot)savefig输出空白图像

问题:Matplotlib(pyplot)savefig输出空白图像

我正在尝试保存使用matplotlib创建的图;但是,图像保存为空白。

这是我的代码:

plt.subplot(121)
plt.imshow(dataStack, cmap=mpl.cm.bone)

plt.subplot(122)
y = copy.deepcopy(tumorStack)
y = np.ma.masked_where(y == 0, y)

plt.imshow(dataStack, cmap=mpl.cm.bone)
plt.imshow(y, cmap=mpl.cm.jet_r, interpolation='nearest')

if T0 is not None:
    plt.subplot(123)
    plt.imshow(T0, cmap=mpl.cm.bone)

    #plt.subplot(124)
    #Autozoom

#else:
    #plt.subplot(124)
    #Autozoom

plt.show()
plt.draw()
plt.savefig('tessstttyyy.png', dpi=100)

tessstttyyy.png为空白(也尝试使用.jpg)

I am trying to save plots I make using matplotlib; however, the images are saving blank.

Here is my code:

plt.subplot(121)
plt.imshow(dataStack, cmap=mpl.cm.bone)

plt.subplot(122)
y = copy.deepcopy(tumorStack)
y = np.ma.masked_where(y == 0, y)

plt.imshow(dataStack, cmap=mpl.cm.bone)
plt.imshow(y, cmap=mpl.cm.jet_r, interpolation='nearest')

if T0 is not None:
    plt.subplot(123)
    plt.imshow(T0, cmap=mpl.cm.bone)

    #plt.subplot(124)
    #Autozoom

#else:
    #plt.subplot(124)
    #Autozoom

plt.show()
plt.draw()
plt.savefig('tessstttyyy.png', dpi=100)

And tessstttyyy.png is blank (also tried with .jpg)


回答 0

首先,什么时候会发生T0 is not None?我会测试一下,然后再调整传递给的值plt.subplot();可以尝试使用值131、132和133,或者取决于是否T0存在的值。

其次,在plt.show()调用之后,创建一个新图形。为了解决这个问题,您可以

  1. 调用plt.savefig('tessstttyyy.png', dpi=100)之前调用plt.show()

  2. show()通过调用plt.gcf()“获取当前图形”来保存图形,然后可以随时调用savefig()Figure对象。

例如:

fig1 = plt.gcf()
plt.show()
plt.draw()
fig1.savefig('tessstttyyy.png', dpi=100)

在您的代码中,“ tesssttyyy.png”为空白,因为它保存的是新图形,该图形上没有任何内容。

First, what happens when T0 is not None? I would test that, then I would adjust the values I pass to plt.subplot(); maybe try values 131, 132, and 133, or values that depend whether or not T0 exists.

Second, after plt.show() is called, a new figure is created. To deal with this, you can

  1. Call plt.savefig('tessstttyyy.png', dpi=100) before you call plt.show()

  2. Save the figure before you show() by calling plt.gcf() for “get current figure”, then you can call savefig() on this Figure object at any time.

For example:

fig1 = plt.gcf()
plt.show()
plt.draw()
fig1.savefig('tessstttyyy.png', dpi=100)

In your code, ‘tesssttyyy.png’ is blank because it is saving the new figure, to which nothing has been plotted.


回答 1

plt.show() 应该来 plt.savefig()

说明:plt.show()清除所有内容,因此以后任何事情都会在一个新的空白图形上发生

plt.show() should come after plt.savefig()

Explanation: plt.show() clears the whole thing, so anything afterwards will happen on a new empty figure


回答 2

更改功能的顺序为我解决了问题

  • 首先 保存情节
  • 然后 显示剧情

如下:

plt.savefig('heatmap.png')

plt.show()

change the order of the functions fixed the problem for me:

  • first Save the plot
  • then Show the plot

as following:

plt.savefig('heatmap.png')

plt.show()

回答 3

在show()对我有用之前调用savefig。

fig ,ax = plt.subplots(figsize = (4,4))
sns.barplot(x='sex', y='tip', color='g', ax=ax,data=tips)
sns.barplot(x='sex', y='tip', color='b', ax=ax,data=tips)
ax.legend(['Male','Female'], facecolor='w')

plt.savefig('figure.png')
plt.show()

Calling savefig before show() worked for me.

fig ,ax = plt.subplots(figsize = (4,4))
sns.barplot(x='sex', y='tip', color='g', ax=ax,data=tips)
sns.barplot(x='sex', y='tip', color='b', ax=ax,data=tips)
ax.legend(['Male','Female'], facecolor='w')

plt.savefig('figure.png')
plt.show()

回答 4

让我给一个更详细的例子:

import numpy as np
import matplotlib.pyplot as plt


def draw_result(lst_iter, lst_loss, lst_acc, title):
    plt.plot(lst_iter, lst_loss, '-b', label='loss')
    plt.plot(lst_iter, lst_acc, '-r', label='accuracy')

    plt.xlabel("n iteration")
    plt.legend(loc='upper left')
    plt.title(title)
    plt.savefig(title+".png")  # should before plt.show method

    plt.show()


def test_draw():
    lst_iter = range(100)
    lst_loss = [0.01 * i + 0.01 * i ** 2 for i in xrange(100)]
    # lst_loss = np.random.randn(1, 100).reshape((100, ))
    lst_acc = [0.01 * i - 0.01 * i ** 2 for i in xrange(100)]
    # lst_acc = np.random.randn(1, 100).reshape((100, ))
    draw_result(lst_iter, lst_loss, lst_acc, "sgd_method")


if __name__ == '__main__':
    test_draw()

let’s me give a more detail example:

import numpy as np
import matplotlib.pyplot as plt


def draw_result(lst_iter, lst_loss, lst_acc, title):
    plt.plot(lst_iter, lst_loss, '-b', label='loss')
    plt.plot(lst_iter, lst_acc, '-r', label='accuracy')

    plt.xlabel("n iteration")
    plt.legend(loc='upper left')
    plt.title(title)
    plt.savefig(title+".png")  # should before plt.show method

    plt.show()


def test_draw():
    lst_iter = range(100)
    lst_loss = [0.01 * i + 0.01 * i ** 2 for i in xrange(100)]
    # lst_loss = np.random.randn(1, 100).reshape((100, ))
    lst_acc = [0.01 * i - 0.01 * i ** 2 for i in xrange(100)]
    # lst_acc = np.random.randn(1, 100).reshape((100, ))
    draw_result(lst_iter, lst_loss, lst_acc, "sgd_method")


if __name__ == '__main__':
    test_draw()


尽管我调用pyplot.show(),但matplotlib不会显示我的绘图

问题:尽管我调用pyplot.show(),但matplotlib不会显示我的绘图

matplotlib上需要帮助。是的,我没有忘记调用pyplot.show()。

$ ipython –pylab

import matplotlib.pyplot as p 
p.plot(range(20), range(20))

matplotlib.lines.Line2D at 0xade2b2c作为输出返回。

p.show()

没事了 没有错误讯息。没有新窗口。没有。我matplotlib使用pip进行安装,但未收到任何错误消息。

细节:

我用,

  • 的Ubuntu
  • IPython v0.11
  • Python v2.6.6
  • matplotlib v1.0.1

Help required on matplotlib. Yes, I did not forget calling the pyplot.show().

$ ipython –pylab

import matplotlib.pyplot as p 
p.plot(range(20), range(20))

It returns matplotlib.lines.Line2D at 0xade2b2c as the output.

p.show()

There is nothing to happen. No error message. No new window. Nothing. I install matplotlib by using pip and I didn’t take any error messages.

Details:

I use,

  • Ubuntu
  • IPython v0.11
  • Python v2.6.6
  • matplotlib v1.0.1

回答 0

如果将后端设置为template~/.matplotlib/matplotlibrc,则可以重现您的症状:

〜/ .matplotlib / matplotlibrc:

# backend      : GtkAgg
backend      : template

请注意,该文件matplotlibrc可能不在目录中~/.matplotlib/。在这种情况下,以下代码显示其位置:

>>> import matplotlib
>>> matplotlib.matplotlib_fname()

In [1]: import matplotlib.pyplot as p

In [2]: p.plot(range(20),range(20))
Out[2]: [<matplotlib.lines.Line2D object at 0xa64932c>]

In [3]: p.show()

如果您~/.matplotlib/matplotlibrc将后端编辑为,并将其更改为GtkAgg,则应该会看到一个图。您可以使用以下命令列出计算机上所有可用的后端

import matplotlib.rcsetup as rcsetup
print(rcsetup.all_backends)

它应该返回类似以下的列表:

['GTK', 'GTKAgg', 'GTKCairo', 'FltkAgg', 'MacOSX', 'QtAgg', 'Qt4Agg',
'TkAgg', 'WX', 'WXAgg', 'CocoaAgg', 'agg', 'cairo', 'emf', 'gdk', 'pdf',
'ps', 'svg', 'template']

参考:

If I set my backend to template in ~/.matplotlib/matplotlibrc, then I can reproduce your symptoms:

~/.matplotlib/matplotlibrc:

# backend      : GtkAgg
backend      : template

Note that the file matplotlibrc may not be in directory ~/.matplotlib/. In this case, the following code shows where it is:

>>> import matplotlib
>>> matplotlib.matplotlib_fname()

In [1]: import matplotlib.pyplot as p

In [2]: p.plot(range(20),range(20))
Out[2]: [<matplotlib.lines.Line2D object at 0xa64932c>]

In [3]: p.show()

If you edit ~/.matplotlib/matplotlibrc and change the backend to something like GtkAgg, you should see a plot. You can list all the backends available on your machine with

import matplotlib.rcsetup as rcsetup
print(rcsetup.all_backends)

It should return a list like:

['GTK', 'GTKAgg', 'GTKCairo', 'FltkAgg', 'MacOSX', 'QtAgg', 'Qt4Agg',
'TkAgg', 'WX', 'WXAgg', 'CocoaAgg', 'agg', 'cairo', 'emf', 'gdk', 'pdf',
'ps', 'svg', 'template']

Reference:


回答 1

我在Ubuntu 12.04上遇到了完全相同的问题,因为我使用以下命令安装了matplotlib(在virtualenv中)

pip install matplotlib

长话短说,我的建议是:不要尝试使用pip或手工安装matplotlib;让真正的软件包管理器(例如apt-get / synaptic)为您安装它及其所有依赖项。

不幸的是,matplotlib的后端(用于实际绘制图的替代方法)具有pip无法处理的各种依赖关系。更糟糕的是,它无声地失败了。也就是说,pip install matplotlib似乎成功安装了matplotlib。但是,当您尝试使用它时(例如pyplot.show()),将不会出现绘图窗口。我尝试了网络上人们建议的所有不同后端(Qt4Agg,GTK等),但它们都失败了(即,当我尝试导入matplotlib.pyplot时,我得到了,ImportError因为它试图导入缺少的某些依赖项)。然后,我研究了如何安装这些依赖项,但这只是让我想放弃使用pip(在virtualenv内)作为任何具有非Python软件包依赖项的软件包的可行安装解决方案。

整个经历使我爬回apt-get / synaptic(即Ubuntu软件包管理器)来安装matplotlib之类的软件。那很好。当然,这意味着您只能安装到您的系统目录中,没有virtualenv的好处,并且您受困于Ubuntu发行的版本,这可能落后于当前版本…

I ran into the exact same problem on Ubuntu 12.04, because I installed matplotlib (within a virtualenv) using

pip install matplotlib

To make long story short, my advice is: don’t try to install matplotlib using pip or by hand; let a real package manager (e.g. apt-get / synaptic) install it and all its dependencies for you.

Unfortunately, matplotlib’s backends (alternative methods for actually rendering your plots) have all sorts of dependencies that pip will not deal with. Even worse, it fails silently; that is, pip install matplotlib appears to install matplotlib successfully. But when you try to use it (e.g. pyplot.show()), no plot window will appear. I tried all the different backends that people on the web suggest (Qt4Agg, GTK, etc.), and they all failed (i.e. when I tried to import matplotlib.pyplot, I get ImportError because it’s trying to import some dependency that’s missing). I then researched how to install those dependencies, but it just made me want to give up using pip (within virtualenv) as a viable installation solution for any package that has non-Python package dependencies.

The whole experience sent me crawling back to apt-get / synaptic (i.e. the Ubuntu package manager) to install software like matplotlib. That worked perfectly. Of course, that means you can only install into your system directories, no virtualenv goodness, and you are stuck with the versions that Ubuntu distributes, which may be way behind the current version…


回答 2

%matplotlib内联

对于使用笔记本的我来说,在绘图工作之前添加以上行。

%matplotlib inline

For me working with notebook, adding the above line before the plot works.


回答 3

备查,

我遇到了同样的问题-pylab没有在ipython下显示。通过更改ipython的配置文件{ipython_config.py}已解决了该问题。在配置文件中

c.InteractiveShellApp.pylab = 'auto'

我将’auto’更改为’qt’,现在我看到了图表

For future reference,

I have encountered the same problem — pylab was not showing under ipython. The problem was fixed by changing ipython’s config file {ipython_config.py}. In the config file

c.InteractiveShellApp.pylab = 'auto'

I changed ‘auto’ to ‘qt’ and now I see graphs


回答 4

只需输入:

plt.ion()

请在23:30 参见https://www.youtube.com/watch?v=1zmV8lZsHF4

plt使用是因为我的导入:import matplotlib.pyplotas plt

我在带有iTerm2的Mac上使用python2.7。

Just type:

plt.ion()

See https://www.youtube.com/watch?v=1zmV8lZsHF4 at 23:30 !

plt is used because of my import: import matplotlib.pyplot as plt

I’m using python2.7 on a mac with iTerm2.


回答 5

解决我问题的方法只是在顶部的ipython Notebook中使用以下两行

%matplotib inline
%pylab inline

而且有效。我正在使用Ubuntu16.04和ipython-5.1

What solved my problem was just using the below two lines in ipython notebook at the top

%matplotib inline
%pylab inline

And it worked. I’m using Ubuntu16.04 and ipython-5.1


回答 6

我必须从源代码安装matplotlib才能使它工作。关键说明(来自http://www.pyimagesearch.com/2015/08/24/resolved-matplotlib-figures-not-showing-up-or-displaying/)为:

$ workon plotting
$ pip uninstall matplotlib
$ git clone https://github.com/matplotlib/matplotlib.git
$ cd matplotlib
$ python setup.py install

正如@unutbu所说,通过更改后端,我遇到了很多问题,所有不同的后端都不起作用。

I had to install matplotlib from source to get this to work. The key instructions (from http://www.pyimagesearch.com/2015/08/24/resolved-matplotlib-figures-not-showing-up-or-displaying/) are:

$ workon plotting
$ pip uninstall matplotlib
$ git clone https://github.com/matplotlib/matplotlib.git
$ cd matplotlib
$ python setup.py install

By changing the backend, as @unutbu says, I just ran into loads more problems with all the different backends not working either.


回答 7

在导入pylab之前添加以下两行似乎对我有用

import matplotlib
matplotlib.use("gtk")

import sys
import pylab
import numpy as np

Adding the following two lines before importing pylab seems to work for me

import matplotlib
matplotlib.use("gtk")

import sys
import pylab
import numpy as np

回答 8

确保启用此启动脚本:(“首选项”>“控制台”>“高级选项”)

/usr/lib/python2.7/dist-packages/spyderlib/scientific_startup.py

如果启用了标准的PYTHONSTARTUP,则不会有交互式绘图

Be sure to have this startup script enabled : ( Preferences > Console > Advanced Options )

/usr/lib/python2.7/dist-packages/spyderlib/scientific_startup.py

If the standard PYTHONSTARTUP is enabled you won’t have an interactive plot


回答 9

类似@Rikki,我通过升级解决了这个问题matplotlibpip install matplotlib --upgrade。如果无法升级,则可以卸载并重新安装。

pip uninstall matplotlib
pip install matplotlib

Similar to @Rikki, I solved this problem by upgrading matplotlib with pip install matplotlib --upgrade. If you can’t upgrade uninstalling and reinstalling may work.

pip uninstall matplotlib
pip install matplotlib

回答 10

对我来说,如果我只是在macOS 下创建一个 matplotlibrc文件,就会发生问题~/.matplotlib。在其中添加“后端:macosx”可解决此问题。

我认为这是一个错误:如果backend未在我的代码中指定,matplotlibrc则应采用默认值。

For me the problem happens if I simply create an empty matplotlibrc file under ~/.matplotlib on macOS. Adding “backend: macosx” in it fixes the problem.

I think it is a bug: if backend is not specified in my matplotlibrc it should take the default value.


回答 11

运行代码后,包括:

import pylab as p
p.show()

After running your code include:

import pylab as p
p.show()

回答 12

我发现我需要window = Tk(),然后window.mainloop()

I found that I needed window = Tk() and then window.mainloop()


回答 13

对于Ubuntu 12.04:

sudo apt-get install python-qt4
virtualenv .env --no-site-packages
source .env/bin/activate
easy_install -U distribute
ln -s /usr/lib/python2.7/dist-packages/PyQt4 .
ln -s /usr/lib/python2.7/dist-packages/sip.so .
pip install matplotlib

For Ubuntu 12.04:

sudo apt-get install python-qt4
virtualenv .env --no-site-packages
source .env/bin/activate
easy_install -U distribute
ln -s /usr/lib/python2.7/dist-packages/PyQt4 .
ln -s /usr/lib/python2.7/dist-packages/sip.so .
pip install matplotlib

在matplotlib中删除已保存图像周围的空白

问题:在matplotlib中删除已保存图像周围的空白

我需要拍摄图像并经过一些处理将其保存。显示该图形时,它看起来不错,但是保存该图形后,在保存的图像周围有一些空白。我尝试过方法的'tight'选项savefig,也没有用。代码:

  import matplotlib.image as mpimg
  import matplotlib.pyplot as plt

  fig = plt.figure(1)
  img = mpimg.imread(path)
  plt.imshow(img)
  ax=fig.add_subplot(1,1,1)

  extent = ax.get_window_extent().transformed(fig.dpi_scale_trans.inverted())
  plt.savefig('1.png', bbox_inches=extent)

  plt.axis('off') 
  plt.show()

我正在尝试通过在图上使用NetworkX绘制基本图形并将其保存。我意识到没有图就可以,但是当添加图时,保存的图像周围会有空白;

import matplotlib.image as mpimg
import matplotlib.pyplot as plt
import networkx as nx

G = nx.Graph()
G.add_node(1)
G.add_node(2)
G.add_node(3)
G.add_edge(1,3)
G.add_edge(1,2)
pos = {1:[100,120], 2:[200,300], 3:[50,75]}

fig = plt.figure(1)
img = mpimg.imread("C:\\images\\1.jpg")
plt.imshow(img)
ax=fig.add_subplot(1,1,1)

nx.draw(G, pos=pos)

extent = ax.get_window_extent().transformed(fig.dpi_scale_trans.inverted())
plt.savefig('1.png', bbox_inches = extent)

plt.axis('off') 
plt.show()

I need to take an image and save it after some process. The figure looks fine when I display it, but after saving the figure, I got some white space around the saved image. I have tried the 'tight' option for savefig method, did not work either. The code:

  import matplotlib.image as mpimg
  import matplotlib.pyplot as plt

  fig = plt.figure(1)
  img = mpimg.imread(path)
  plt.imshow(img)
  ax=fig.add_subplot(1,1,1)

  extent = ax.get_window_extent().transformed(fig.dpi_scale_trans.inverted())
  plt.savefig('1.png', bbox_inches=extent)

  plt.axis('off') 
  plt.show()

I am trying to draw a basic graph by using NetworkX on a figure and save it. I realized that without graph it works, but when added a graph I get white space around the saved image;

import matplotlib.image as mpimg
import matplotlib.pyplot as plt
import networkx as nx

G = nx.Graph()
G.add_node(1)
G.add_node(2)
G.add_node(3)
G.add_edge(1,3)
G.add_edge(1,2)
pos = {1:[100,120], 2:[200,300], 3:[50,75]}

fig = plt.figure(1)
img = mpimg.imread("C:\\images\\1.jpg")
plt.imshow(img)
ax=fig.add_subplot(1,1,1)

nx.draw(G, pos=pos)

extent = ax.get_window_extent().transformed(fig.dpi_scale_trans.inverted())
plt.savefig('1.png', bbox_inches = extent)

plt.axis('off') 
plt.show()

回答 0

我不能说我确切知道我的“解决方案”为什么起作用或如何起作用,但是当我想将几个翼型截面的轮廓(没有白色边距)绘制到PDF文件时,这就是我要做的。(请注意,我在带有-pylab标志的IPython笔记本中使用了matplotlib。)

plt.gca().set_axis_off()
plt.subplots_adjust(top = 1, bottom = 0, right = 1, left = 0, 
            hspace = 0, wspace = 0)
plt.margins(0,0)
plt.gca().xaxis.set_major_locator(plt.NullLocator())
plt.gca().yaxis.set_major_locator(plt.NullLocator())
plt.savefig("filename.pdf", bbox_inches = 'tight',
    pad_inches = 0)

我尝试停用此功能的不同部分,但这总是在某处导致空白。您甚至可以对此进行修改,以防止由于缺乏边距而使图形附近的粗线被刮掉。

I cannot claim I know exactly why or how my “solution” works, but this is what I had to do when I wanted to plot the outline of a couple of aerofoil sections — without white margins — to a PDF file. (Note that I used matplotlib inside an IPython notebook, with the -pylab flag.)

plt.gca().set_axis_off()
plt.subplots_adjust(top = 1, bottom = 0, right = 1, left = 0, 
            hspace = 0, wspace = 0)
plt.margins(0,0)
plt.gca().xaxis.set_major_locator(plt.NullLocator())
plt.gca().yaxis.set_major_locator(plt.NullLocator())
plt.savefig("filename.pdf", bbox_inches = 'tight',
    pad_inches = 0)

I have tried to deactivate different parts of this, but this always lead to a white margin somewhere. You may even have modify this to keep fat lines near the limits of the figure from being shaved by the lack of margins.


回答 1

您可以通过bbox_inches="tight"在中设置来删除空白填充savefig

plt.savefig("test.png",bbox_inches='tight')

您必须将参数bbox_inches作为字符串输入,也许这就是为什么它对您较早不起作用的原因。


可能重复:

Matplotlib图:删除轴,图例和空白

如何设置matplotlib图形的边距?

减少matplotlib图中的左右边距

You can remove the white space padding by setting bbox_inches="tight" in savefig:

plt.savefig("test.png",bbox_inches='tight')

You’ll have to put the argument to bbox_inches as a string, perhaps this is why it didn’t work earlier for you.


Possible duplicates:

Matplotlib plots: removing axis, legends and white spaces

How to set the margins for a matplotlib figure?

Reduce left and right margins in matplotlib plot


回答 2

在尝试了上述答案但没有成功(以及许多其他堆栈文章)之后,最终对我有用的只是

plt.gca().set_axis_off()
plt.subplots_adjust(top = 1, bottom = 0, right = 1, left = 0, 
            hspace = 0, wspace = 0)
plt.margins(0,0)
plt.savefig("myfig.pdf")

重要的是,这不包括bbox或padding参数。

After trying the above answers with no success (and a slew of other stack posts) what finally worked for me was just

plt.gca().set_axis_off()
plt.subplots_adjust(top = 1, bottom = 0, right = 1, left = 0, 
            hspace = 0, wspace = 0)
plt.margins(0,0)
plt.savefig("myfig.pdf")

Importantly this does not include the bbox or padding arguments.


回答 3

我从Arvind Pereira(http://robotics.usc.edu/~ampereir/wordpress/?p=626)找到了一些东西,似乎对我有用:

plt.savefig(filename, transparent = True, bbox_inches = 'tight', pad_inches = 0)

I found something from Arvind Pereira (http://robotics.usc.edu/~ampereir/wordpress/?p=626) and seemed to work for me:

plt.savefig(filename, transparent = True, bbox_inches = 'tight', pad_inches = 0)

回答 4

以下功能合并了上面的johannes-s答案。我有测试过plt.figure,并plt.subplots()与多个轴,它工作得很好。

def save(filepath, fig=None):
    '''Save the current image with no whitespace
    Example filepath: "myfig.png" or r"C:\myfig.pdf" 
    '''
    import matplotlib.pyplot as plt
    if not fig:
        fig = plt.gcf()

    plt.subplots_adjust(0,0,1,1,0,0)
    for ax in fig.axes:
        ax.axis('off')
        ax.margins(0,0)
        ax.xaxis.set_major_locator(plt.NullLocator())
        ax.yaxis.set_major_locator(plt.NullLocator())
    fig.savefig(filepath, pad_inches = 0, bbox_inches='tight')

The following function incorporates johannes-s answer above. I have tested it with plt.figure and plt.subplots() with multiple axes, and it works nicely.

def save(filepath, fig=None):
    '''Save the current image with no whitespace
    Example filepath: "myfig.png" or r"C:\myfig.pdf" 
    '''
    import matplotlib.pyplot as plt
    if not fig:
        fig = plt.gcf()

    plt.subplots_adjust(0,0,1,1,0,0)
    for ax in fig.axes:
        ax.axis('off')
        ax.margins(0,0)
        ax.xaxis.set_major_locator(plt.NullLocator())
        ax.yaxis.set_major_locator(plt.NullLocator())
    fig.savefig(filepath, pad_inches = 0, bbox_inches='tight')

回答 5

我发现以下代码非常适合这项工作。

fig = plt.figure(figsize=[6,6])
ax = fig.add_subplot(111)
ax.imshow(data)
ax.axes.get_xaxis().set_visible(False)
ax.axes.get_yaxis().set_visible(False)
ax.set_frame_on(False)
plt.savefig('data.png', dpi=400, bbox_inches='tight',pad_inches=0)

I found the following codes work perfectly for the job.

fig = plt.figure(figsize=[6,6])
ax = fig.add_subplot(111)
ax.imshow(data)
ax.axes.get_xaxis().set_visible(False)
ax.axes.get_yaxis().set_visible(False)
ax.set_frame_on(False)
plt.savefig('data.png', dpi=400, bbox_inches='tight',pad_inches=0)

回答 6

我遵循了这个顺序,它就像一个魅力。

plt.axis("off")
fig=plt.imshow(image array,interpolation='nearest')
fig.axes.get_xaxis().set_visible(False)
fig.axes.get_yaxis().set_visible(False)
plt.savefig('destination_path.pdf',
    bbox_inches='tight', pad_inches=0, format='pdf', dpi=1200)

i followed this sequence and it worked like a charm.

plt.axis("off")
fig=plt.imshow(image array,interpolation='nearest')
fig.axes.get_xaxis().set_visible(False)
fig.axes.get_yaxis().set_visible(False)
plt.savefig('destination_path.pdf',
    bbox_inches='tight', pad_inches=0, format='pdf', dpi=1200)

回答 7

对于任何想以像素而不是英寸为单位的人,都可以使用。

加上平时您还需要

from matplotlib.transforms import Bbox

然后,您可以使用以下命令:

my_dpi = 100 # Good default - doesn't really matter

# Size of output in pixels
h = 224
w = 224

fig, ax = plt.subplots(1, figsize=(w/my_dpi, h/my_dpi), dpi=my_dpi)

ax.set_position([0, 0, 1, 1]) # Critical!

# Do some stuff
ax.imshow(img)
ax.imshow(heatmap) # 4-channel RGBA
ax.plot([50, 100, 150], [50, 100, 150], color="red")

ax.axis("off")

fig.savefig("saved_img.png",
            bbox_inches=Bbox([[0, 0], [w/my_dpi, h/my_dpi]]),
            dpi=my_dpi)

For anyone who wants to work in pixels rather than inches this will work.

Plus the usual you will also need

from matplotlib.transforms import Bbox

Then you can use the following:

my_dpi = 100 # Good default - doesn't really matter

# Size of output in pixels
h = 224
w = 224

fig, ax = plt.subplots(1, figsize=(w/my_dpi, h/my_dpi), dpi=my_dpi)

ax.set_position([0, 0, 1, 1]) # Critical!

# Do some stuff
ax.imshow(img)
ax.imshow(heatmap) # 4-channel RGBA
ax.plot([50, 100, 150], [50, 100, 150], color="red")

ax.axis("off")

fig.savefig("saved_img.png",
            bbox_inches=Bbox([[0, 0], [w/my_dpi, h/my_dpi]]),
            dpi=my_dpi)


回答 8

我发现一种更简单的方法是使用plt.imsave

    import matplotlib.pyplot as plt
    arr = plt.imread(path)
    plt.imsave('test.png', arr)

A much simpler approach I found is to use plt.imsave :

    import matplotlib.pyplot as plt
    arr = plt.imread(path)
    plt.imsave('test.png', arr)

回答 9

您可以尝试一下。它解决了我的问题。

import matplotlib.image as mpimg
img = mpimg.imread("src.png")
mpimg.imsave("out.png", img, cmap=cmap)

You may try this. It solved my issue.

import matplotlib.image as mpimg
img = mpimg.imread("src.png")
mpimg.imsave("out.png", img, cmap=cmap)

回答 10

如果要显示要保存的内容,我建议您使用plt.tight_layout转换,因为它在使用时不会进行不必要的裁剪,因此实际上更可取plt.savefig

import matplotlib as plt    
plt.plot([1,2,3], [1,2,3])
plt.tight_layout(pad=0)
plt.savefig('plot.png')

The most straightforward method is to use plt.tight_layout transformation which is actually more preferable as it doesn’t do unnecessary cropping when using plt.savefig

import matplotlib as plt    
plt.plot([1,2,3], [1,2,3])
plt.tight_layout(pad=0)
plt.savefig('plot.png')

However, this may not be preferable for complex plots that modifies the figure. Refer to top answers that uses plt.subplots_adjust if that’s the case.


回答 11

这对我有用,将用imshow绘制的numpy数组保存到文件

import matplotlib.pyplot as plt

fig = plt.figure(figsize=(10,10))
plt.imshow(img) # your image here
plt.axis("off")
plt.subplots_adjust(top = 1, bottom = 0, right = 1, left = 0, 
        hspace = 0, wspace = 0)
plt.savefig("example2.png", box_inches='tight', dpi=100)
plt.show()

This works for me saving a numpy array plotted with imshow to file

import matplotlib.pyplot as plt

fig = plt.figure(figsize=(10,10))
plt.imshow(img) # your image here
plt.axis("off")
plt.subplots_adjust(top = 1, bottom = 0, right = 1, left = 0, 
        hspace = 0, wspace = 0)
plt.savefig("example2.png", box_inches='tight', dpi=100)
plt.show()

如何将Seaborn图保存到文件中

问题:如何将Seaborn图保存到文件中

我尝试了以下代码(test_seaborn.py):

import matplotlib
matplotlib.use('Agg')
import matplotlib.pyplot as plt
matplotlib.style.use('ggplot')
import seaborn as sns
sns.set()
df = sns.load_dataset('iris')
sns_plot = sns.pairplot(df, hue='species', size=2.5)
fig = sns_plot.get_figure()
fig.savefig("output.png")
#sns.plt.show()

但是我得到这个错误:

  Traceback (most recent call last):
  File "test_searborn.py", line 11, in <module>
    fig = sns_plot.get_figure()
AttributeError: 'PairGrid' object has no attribute 'get_figure'

我希望决赛output.png将存在,看起来像这样:

我该如何解决该问题?

I tried the following code (test_seaborn.py):

import matplotlib
matplotlib.use('Agg')
import matplotlib.pyplot as plt
matplotlib.style.use('ggplot')
import seaborn as sns
sns.set()
df = sns.load_dataset('iris')
sns_plot = sns.pairplot(df, hue='species', size=2.5)
fig = sns_plot.get_figure()
fig.savefig("output.png")
#sns.plt.show()

But I get this error:

  Traceback (most recent call last):
  File "test_searborn.py", line 11, in <module>
    fig = sns_plot.get_figure()
AttributeError: 'PairGrid' object has no attribute 'get_figure'

I expect the final output.png will exist and look like this:

How can I resolve the problem?


回答 0

删除get_figure并使用sns_plot.savefig('output.png')

df = sns.load_dataset('iris')
sns_plot = sns.pairplot(df, hue='species', size=2.5)
sns_plot.savefig("output.png")

Remove the get_figure and just use sns_plot.savefig('output.png')

df = sns.load_dataset('iris')
sns_plot = sns.pairplot(df, hue='species', size=2.5)
sns_plot.savefig("output.png")

回答 1

建议的解决方案与Seaborn 0.8.1不兼容

由于Seaborn界面已更改,因此出现以下错误:

AttributeError: 'AxesSubplot' object has no attribute 'fig'
When trying to access the figure

AttributeError: 'AxesSubplot' object has no attribute 'savefig'
when trying to use the savefig directly as a function

以下调用允许您访问该图(与Seaborn 0.8.1兼容):

swarm_plot = sns.swarmplot(...)
fig = swarm_plot.get_figure()
fig.savefig(...) 

如先前在此答案中所见。

更新: 我最近使用了seaborn的PairGrid对象生成了一个类似于本示例中的图。在这种情况下,由于GridPlot不是像sns.swarmplot这样的绘图对象,因此它没有get_figure()函数。可以通过以下方式直接访问matplotlib图

fig = myGridPlotObject.fig

就像之前在该主题的其他文章中建议的那样。

The suggested solutions are incompatible with Seaborn 0.8.1

giving the following errors because the Seaborn interface has changed:

AttributeError: 'AxesSubplot' object has no attribute 'fig'
When trying to access the figure

AttributeError: 'AxesSubplot' object has no attribute 'savefig'
when trying to use the savefig directly as a function

The following calls allow you to access the figure (Seaborn 0.8.1 compatible):

swarm_plot = sns.swarmplot(...)
fig = swarm_plot.get_figure()
fig.savefig(...) 

as seen previously in this answer.

UPDATE: I have recently used PairGrid object from seaborn to generate a plot similar to the one in this example. In this case, since GridPlot is not a plot object like, for example, sns.swarmplot, it has no get_figure() function. It is possible to directly access the matplotlib figure by

fig = myGridPlotObject.fig

Like previously suggested in other posts in this thread.


回答 2

上述某些解决方案对我不起作用。.fig尝试该属性时未找到该属性,因此无法.savefig()直接使用。但是,起作用的是:

sns_plot.figure.savefig("output.png")

我是Python新用户,所以我不知道这是否是由于更新引起的。我想提一下,以防其他人遇到和我一样的问题。

Some of the above solutions did not work for me. The .fig attribute was not found when I tried that and I was unable to use .savefig() directly. However, what did work was:

sns_plot.figure.savefig("output.png")

I am a newer Python user, so I do not know if this is due to an update. I wanted to mention it in case anybody else runs into the same issues as I did.


回答 3

您应该只能够直接使用savefig方法sns_plot

sns_plot.savefig("output.png")

为了使您的代码更加清晰,如果您确实要访问sns_plot驻留在其中的matplotlib图形,则可以直接通过

fig = sns_plot.fig

在这种情况下get_figure,您的代码将假定没有方法。

You should just be able to use the savefig method of sns_plot directly.

sns_plot.savefig("output.png")

For clarity with your code if you did want to access the matplotlib figure that sns_plot resides in then you can get it directly with

fig = sns_plot.fig

In this case there is no get_figure method as your code assumes.


回答 4

我使用distplotget_figure成功保存了图片。

sns_hist = sns.distplot(df_train['SalePrice'])
fig = sns_hist.get_figure()
fig.savefig('hist.png')

I use distplot and get_figure to save picture successfully.

sns_hist = sns.distplot(df_train['SalePrice'])
fig = sns_hist.get_figure()
fig.savefig('hist.png')

回答 5

2019年搜索者的台词更少:

import matplotlib.pyplot as plt
import seaborn as sns

df = sns.load_dataset('iris')
sns_plot = sns.pairplot(df, hue='species', height=2.5)
plt.savefig('output.png')

更新说明:size已更改为height

Fewer lines for 2019 searchers:

import matplotlib.pyplot as plt
import seaborn as sns

df = sns.load_dataset('iris')
sns_plot = sns.pairplot(df, hue='species', height=2.5)
plt.savefig('output.png')

UPDATE NOTE: size was changed to height.


回答 6

这对我有用

import seaborn as sns
import matplotlib.pyplot as plt
%matplotlib inline

sns.factorplot(x='holiday',data=data,kind='count',size=5,aspect=1)
plt.savefig('holiday-vs-count.png')

This works for me

import seaborn as sns
import matplotlib.pyplot as plt
%matplotlib inline

sns.factorplot(x='holiday',data=data,kind='count',size=5,aspect=1)
plt.savefig('holiday-vs-count.png')

回答 7

也可以只创建一个matplotlib figure对象,然后使用plt.savefig(...)

from matplotlib import pyplot as plt
import seaborn as sns
import pandas as pd

df = sns.load_dataset('iris')
plt.figure() # Push new figure on stack
sns_plot = sns.pairplot(df, hue='species', size=2.5)
plt.savefig('output.png') # Save that figure

Its also possible to just create a matplotlib figure object and then use plt.savefig(...):

from matplotlib import pyplot as plt
import seaborn as sns
import pandas as pd

df = sns.load_dataset('iris')
plt.figure() # Push new figure on stack
sns_plot = sns.pairplot(df, hue='species', size=2.5)
plt.savefig('output.png') # Save that figure

回答 8

sns.figure.savefig("output.png")在seaborn 0.8.1中使用会出错。

而是使用:

import seaborn as sns

df = sns.load_dataset('iris')
sns_plot = sns.pairplot(df, hue='species', size=2.5)
sns_plot.savefig("output.png")

You would get an error for using sns.figure.savefig("output.png") in seaborn 0.8.1.

Instead use:

import seaborn as sns

df = sns.load_dataset('iris')
sns_plot = sns.pairplot(df, hue='species', size=2.5)
sns_plot.savefig("output.png")

回答 9

仅供参考,下面的命令在seaborn 0.8.1中起作用,因此我想最初的答案仍然有效。

sns_plot = sns.pairplot(data, hue='species', size=3)
sns_plot.savefig("output.png")

Just FYI, the below command worked in seaborn 0.8.1 so I guess the initial answer is still valid.

sns_plot = sns.pairplot(data, hue='species', size=3)
sns_plot.savefig("output.png")

使用Matplotlib绘制2D热图

问题:使用Matplotlib绘制2D热图

我想使用Matplotlib绘制2D热图。我的数据是一个n×n的Numpy数组,每个数组的值都在0到1之间。因此,对于该数组的(i,j)元素,我想在我的(i,j)坐标上绘制一个正方形热图,其颜色与数组中元素的值成比例。

我怎样才能做到这一点?

Using Matplotlib, I want to plot a 2D heat map. My data is an n-by-n Numpy array, each with a value between 0 and 1. So for the (i, j) element of this array, I want to plot a square at the (i, j) coordinate in my heat map, whose color is proportional to the element’s value in the array.

How can I do this?


回答 0

imshow()函数带有参数interpolation='nearest'cmap='hot'应该执行您想要的操作。

import matplotlib.pyplot as plt
import numpy as np

a = np.random.random((16, 16))
plt.imshow(a, cmap='hot', interpolation='nearest')
plt.show()

The imshow() function with parameters interpolation='nearest' and cmap='hot' should do what you want.

import matplotlib.pyplot as plt
import numpy as np

a = np.random.random((16, 16))
plt.imshow(a, cmap='hot', interpolation='nearest')
plt.show()


回答 1

Seaborn负责许多手动工作,并自动在图表的侧面绘制渐变等。

import numpy as np
import seaborn as sns
import matplotlib.pylab as plt

uniform_data = np.random.rand(10, 12)
ax = sns.heatmap(uniform_data, linewidth=0.5)
plt.show()

或者,您甚至可以绘制正方形矩阵的上/下左/右三角形,例如,一个正方形且对称的相关矩阵,因此绘制所有值无论如何都是多余的。

corr = np.corrcoef(np.random.randn(10, 200))
mask = np.zeros_like(corr)
mask[np.triu_indices_from(mask)] = True
with sns.axes_style("white"):
    ax = sns.heatmap(corr, mask=mask, vmax=.3, square=True,  cmap="YlGnBu")
    plt.show()

Seaborn takes care of a lot of the manual work and automatically plots a gradient at the side of the chart etc.

import numpy as np
import seaborn as sns
import matplotlib.pylab as plt

uniform_data = np.random.rand(10, 12)
ax = sns.heatmap(uniform_data, linewidth=0.5)
plt.show()

Or, you can even plot upper / lower left / right triangles of square matrices, for example a correlation matrix which is square and is symmetric, so plotting all values would be redundant anyway.

corr = np.corrcoef(np.random.randn(10, 200))
mask = np.zeros_like(corr)
mask[np.triu_indices_from(mask)] = True
with sns.axes_style("white"):
    ax = sns.heatmap(corr, mask=mask, vmax=.3, square=True,  cmap="YlGnBu")
    plt.show()


回答 2

对于二维numpy数组,简单地使用imshow()可能会帮助您:

import matplotlib.pyplot as plt
import numpy as np


def heatmap2d(arr: np.ndarray):
    plt.imshow(arr, cmap='viridis')
    plt.colorbar()
    plt.show()


test_array = np.arange(100 * 100).reshape(100, 100)
heatmap2d(test_array)

此代码产生连续的热图。

您可以colormap这里选择另一个内置的。

For a 2d numpy array, simply use imshow() may help you:

import matplotlib.pyplot as plt
import numpy as np


def heatmap2d(arr: np.ndarray):
    plt.imshow(arr, cmap='viridis')
    plt.colorbar()
    plt.show()


test_array = np.arange(100 * 100).reshape(100, 100)
heatmap2d(test_array)

This code produces a continuous heatmap.

You can choose another built-in colormap from here.


回答 3

我会使用matplotlib的pcolor / pcolormesh函数,因为它允许数据间距不均匀。

取自matplotlib的示例:

import matplotlib.pyplot as plt
import numpy as np

# generate 2 2d grids for the x & y bounds
y, x = np.meshgrid(np.linspace(-3, 3, 100), np.linspace(-3, 3, 100))

z = (1 - x / 2. + x ** 5 + y ** 3) * np.exp(-x ** 2 - y ** 2)
# x and y are bounds, so z should be the value *inside* those bounds.
# Therefore, remove the last value from the z array.
z = z[:-1, :-1]
z_min, z_max = -np.abs(z).max(), np.abs(z).max()

fig, ax = plt.subplots()

c = ax.pcolormesh(x, y, z, cmap='RdBu', vmin=z_min, vmax=z_max)
ax.set_title('pcolormesh')
# set the limits of the plot to the limits of the data
ax.axis([x.min(), x.max(), y.min(), y.max()])
fig.colorbar(c, ax=ax)

plt.show()

I would use matplotlib’s pcolor/pcolormesh function since it allows nonuniform spacing of the data.

Example taken from matplotlib:

import matplotlib.pyplot as plt
import numpy as np

# generate 2 2d grids for the x & y bounds
y, x = np.meshgrid(np.linspace(-3, 3, 100), np.linspace(-3, 3, 100))

z = (1 - x / 2. + x ** 5 + y ** 3) * np.exp(-x ** 2 - y ** 2)
# x and y are bounds, so z should be the value *inside* those bounds.
# Therefore, remove the last value from the z array.
z = z[:-1, :-1]
z_min, z_max = -np.abs(z).max(), np.abs(z).max()

fig, ax = plt.subplots()

c = ax.pcolormesh(x, y, z, cmap='RdBu', vmin=z_min, vmax=z_max)
ax.set_title('pcolormesh')
# set the limits of the plot to the limits of the data
ax.axis([x.min(), x.max(), y.min(), y.max()])
fig.colorbar(c, ax=ax)

plt.show()


回答 4

这是从csv执行操作的方法:

import numpy as np
import matplotlib.pyplot as plt
from scipy.interpolate import griddata

# Load data from CSV
dat = np.genfromtxt('dat.xyz', delimiter=' ',skip_header=0)
X_dat = dat[:,0]
Y_dat = dat[:,1]
Z_dat = dat[:,2]

# Convert from pandas dataframes to numpy arrays
X, Y, Z, = np.array([]), np.array([]), np.array([])
for i in range(len(X_dat)):
        X = np.append(X, X_dat[i])
        Y = np.append(Y, Y_dat[i])
        Z = np.append(Z, Z_dat[i])

# create x-y points to be used in heatmap
xi = np.linspace(X.min(), X.max(), 1000)
yi = np.linspace(Y.min(), Y.max(), 1000)

# Z is a matrix of x-y values
zi = griddata((X, Y), Z, (xi[None,:], yi[:,None]), method='cubic')

# I control the range of my colorbar by removing data 
# outside of my range of interest
zmin = 3
zmax = 12
zi[(zi<zmin) | (zi>zmax)] = None

# Create the contour plot
CS = plt.contourf(xi, yi, zi, 15, cmap=plt.cm.rainbow,
                  vmax=zmax, vmin=zmin)
plt.colorbar()  
plt.show()

dat.xyz形式在哪里

x1 y1 z1
x2 y2 z2
...

Here’s how to do it from a csv:

import numpy as np
import matplotlib.pyplot as plt
from scipy.interpolate import griddata

# Load data from CSV
dat = np.genfromtxt('dat.xyz', delimiter=' ',skip_header=0)
X_dat = dat[:,0]
Y_dat = dat[:,1]
Z_dat = dat[:,2]

# Convert from pandas dataframes to numpy arrays
X, Y, Z, = np.array([]), np.array([]), np.array([])
for i in range(len(X_dat)):
        X = np.append(X, X_dat[i])
        Y = np.append(Y, Y_dat[i])
        Z = np.append(Z, Z_dat[i])

# create x-y points to be used in heatmap
xi = np.linspace(X.min(), X.max(), 1000)
yi = np.linspace(Y.min(), Y.max(), 1000)

# Z is a matrix of x-y values
zi = griddata((X, Y), Z, (xi[None,:], yi[:,None]), method='cubic')

# I control the range of my colorbar by removing data 
# outside of my range of interest
zmin = 3
zmax = 12
zi[(zi<zmin) | (zi>zmax)] = None

# Create the contour plot
CS = plt.contourf(xi, yi, zi, 15, cmap=plt.cm.rainbow,
                  vmax=zmax, vmin=zmin)
plt.colorbar()  
plt.show()

where dat.xyz is in the form

x1 y1 z1
x2 y2 z2
...

matplotlib:如何在图像上绘制矩形

问题:matplotlib:如何在图像上绘制矩形

如何在图像上绘制矩形,如下所示:

import matplotlib.pyplot as plt
from PIL import Image
import numpy as np
im = np.array(Image.open('dog.png'), dtype=np.uint8)
plt.imshow(im)

我不知道该如何进行。

How to draw a rectangle on an image, like this:

import matplotlib.pyplot as plt
from PIL import Image
import numpy as np
im = np.array(Image.open('dog.png'), dtype=np.uint8)
plt.imshow(im)

I don’t know how to proceed.


回答 0

您可以将Rectangle补丁添加到matplotlib轴。

例如(在此处使用教程中的图像):

import matplotlib.pyplot as plt
import matplotlib.patches as patches
from PIL import Image
import numpy as np

im = np.array(Image.open('stinkbug.png'), dtype=np.uint8)

# Create figure and axes
fig,ax = plt.subplots(1)

# Display the image
ax.imshow(im)

# Create a Rectangle patch
rect = patches.Rectangle((50,100),40,30,linewidth=1,edgecolor='r',facecolor='none')

# Add the patch to the Axes
ax.add_patch(rect)

plt.show()

You can add a Rectangle patch to the matplotlib Axes.

For example (using the image from the tutorial here):

import matplotlib.pyplot as plt
import matplotlib.patches as patches
from PIL import Image
import numpy as np

im = np.array(Image.open('stinkbug.png'), dtype=np.uint8)

# Create figure and axes
fig,ax = plt.subplots(1)

# Display the image
ax.imshow(im)

# Create a Rectangle patch
rect = patches.Rectangle((50,100),40,30,linewidth=1,edgecolor='r',facecolor='none')

# Add the patch to the Axes
ax.add_patch(rect)

plt.show()


回答 1

您需要使用补丁。

import matplotlib.pyplot as plt
import matplotlib.patches as patches

fig2 = plt.figure()
ax2 = fig2.add_subplot(111, aspect='equal')

ax2.add_patch(
     patches.Rectangle(
        (0.1, 0.1),
        0.5,
        0.5,
        fill=False      # remove background
     ) ) 
fig2.savefig('rect2.png', dpi=90, bbox_inches='tight')

You need use patches.

import matplotlib.pyplot as plt
import matplotlib.patches as patches

fig2 = plt.figure()
ax2 = fig2.add_subplot(111, aspect='equal')

ax2.add_patch(
     patches.Rectangle(
        (0.1, 0.1),
        0.5,
        0.5,
        fill=False      # remove background
     ) ) 
fig2.savefig('rect2.png', dpi=90, bbox_inches='tight')

回答 2

不需要子图,并且pyplot可以显示PIL图像,因此可以进一步简化:

import matplotlib.pyplot as plt
from matplotlib.patches import Rectangle
from PIL import Image

im = Image.open('stinkbug.png')

# Display the image
plt.imshow(im)

# Get the current reference
ax = plt.gca()

# Create a Rectangle patch
rect = Rectangle((50,100),40,30,linewidth=1,edgecolor='r',facecolor='none')

# Add the patch to the Axes
ax.add_patch(rect)

或者,简短版本:

import matplotlib.pyplot as plt
from matplotlib.patches import Rectangle
from PIL import Image

# Display the image
plt.imshow(Image.open('stinkbug.png'))

# Add the patch to the Axes
plt.gca().add_patch(Rectangle((50,100),40,30,linewidth=1,edgecolor='r',facecolor='none'))

There is no need for subplots, and pyplot can display PIL images, so this can be simplified further:

import matplotlib.pyplot as plt
from matplotlib.patches import Rectangle
from PIL import Image

im = Image.open('stinkbug.png')

# Display the image
plt.imshow(im)

# Get the current reference
ax = plt.gca()

# Create a Rectangle patch
rect = Rectangle((50,100),40,30,linewidth=1,edgecolor='r',facecolor='none')

# Add the patch to the Axes
ax.add_patch(rect)

Or, the short version:

import matplotlib.pyplot as plt
from matplotlib.patches import Rectangle
from PIL import Image

# Display the image
plt.imshow(Image.open('stinkbug.png'))

# Add the patch to the Axes
plt.gca().add_patch(Rectangle((50,100),40,30,linewidth=1,edgecolor='r',facecolor='none'))

回答 3

据我了解,matplotlib是一个绘图库。

如果要更改图像数据(例如,在图像上绘制矩形),则可以使用PIL的ImageDrawOpenCV或类似的东西。

这是PIL的ImageDraw方法来绘制矩形

这是OpenCV绘制矩形的方法之一

您的问题询问了有关Matplotlib的问题,但可能应该只是询问有关在图像上绘制矩形的问题。

这是另一个解决我想知道的问题的问题: 使用PIL在其中绘制一个矩形和一个文本

From my understanding matplotlib is a plotting library.

If you want to change the image data (e.g. draw a rectangle on an image), you could use PIL’s ImageDraw, OpenCV, or something similar.

Here is PIL’s ImageDraw method to draw a rectangle.

Here is one of OpenCV’s methods for drawing a rectangle.

Your question asked about Matplotlib, but probably should have just asked about drawing a rectangle on an image.

Here is another question which addresses what I think you wanted to know: Draw a rectangle and a text in it using PIL


使用Matplotlib以非阻塞方式绘制

问题:使用Matplotlib以非阻塞方式绘制

最近几天,我一直在玩Numpy和matplotlib。我在尝试使matplotlib绘制函数而不阻止执行时遇到问题。我知道这里已经有很多线程在问类似的问题,并且我已经在Google上搜索了很多,但是还没有成功完成这项工作。

我曾尝试按照某些人的建议使用show(block = False),但是我得到的只是一个冻结的窗口。如果我简单地调用show(),则将正确绘制结果,但执行将被阻塞,直到关闭窗口为止。从我读过的其他线程中,我怀疑show(block = False)是否起作用取决于后端。这样对吗?我的后端是Qt4Agg。您能否看一下我的代码,并告诉我是否看到错误?这是我的代码。谢谢你的帮助。

from math import *
from matplotlib import pyplot as plt
print plt.get_backend()



def main():
    x = range(-50, 51, 1)
    for pow in range(1,5):   # plot x^1, x^2, ..., x^4

        y = [Xi**pow for Xi in x]
        print y

        plt.plot(x, y)
        plt.draw()
        #plt.show()             #this plots correctly, but blocks execution.
        plt.show(block=False)   #this creates an empty frozen window.
        _ = raw_input("Press [enter] to continue.")


if __name__ == '__main__':
    main()

PS。我忘了说,我想在每次绘制图形时都更新现有窗口,而不是创建一个新窗口。

I have been playing with Numpy and matplotlib in the last few days. I am having problems trying to make matplotlib plot a function without blocking execution. I know there are already many threads here on SO asking similar questions, and I ‘ve googled quite a lot but haven’t managed to make this work.

I have tried using show(block=False) as some people suggest, but all I get is a frozen window. If I simply call show(), the result is plotted properly but execution is blocked until the window is closed. From other threads I ‘ve read, I suspect that whether show(block=False) works or not depends on the backend. Is this correct? My back end is Qt4Agg. Could you have a look at my code and tell me if you see something wrong? Here is my code. Thanks for any help.

from math import *
from matplotlib import pyplot as plt
print plt.get_backend()



def main():
    x = range(-50, 51, 1)
    for pow in range(1,5):   # plot x^1, x^2, ..., x^4

        y = [Xi**pow for Xi in x]
        print y

        plt.plot(x, y)
        plt.draw()
        #plt.show()             #this plots correctly, but blocks execution.
        plt.show(block=False)   #this creates an empty frozen window.
        _ = raw_input("Press [enter] to continue.")


if __name__ == '__main__':
    main()

PS. I forgot to say that I would like to update the existing window every time I plot something, instead of creating a new one.


回答 0

我花了很长时间寻找解决方案,并找到了答案

看起来,为了获得您(和我)想要的东西,您需要将plt.ion()plt.show()(而不是与block=False)结合在一起,最重要的是,plt.pause(.001)(或您想要的任何时间)结合在一起。该暂停是必须的,因为GUI事件,而主代码正在睡觉,包括绘图发生。这很可能是通过从休眠线程中获取时间来实现的,所以IDE可能会为此惹恼我不知道。

这是对我适用于python 3.5的实现:

import numpy as np
from matplotlib import pyplot as plt

def main():
    plt.axis([-50,50,0,10000])
    plt.ion()
    plt.show()

    x = np.arange(-50, 51)
    for pow in range(1,5):   # plot x^1, x^2, ..., x^4
        y = [Xi**pow for Xi in x]
        plt.plot(x, y)
        plt.draw()
        plt.pause(0.001)
        input("Press [enter] to continue.")

if __name__ == '__main__':
    main()

I spent a long time looking for solutions, and found this answer.

It looks like, in order to get what you (and I) want, you need the combination of plt.ion(), plt.show() (not with block=False) and, most importantly, plt.pause(.001) (or whatever time you want). The pause is needed because the GUI events happen while the main code is sleeping, including drawing. It’s possible that this is implemented by picking up time from a sleeping thread, so maybe IDEs mess with that—I don’t know.

Here’s an implementation that works for me on python 3.5:

import numpy as np
from matplotlib import pyplot as plt

def main():
    plt.axis([-50,50,0,10000])
    plt.ion()
    plt.show()

    x = np.arange(-50, 51)
    for pow in range(1,5):   # plot x^1, x^2, ..., x^4
        y = [Xi**pow for Xi in x]
        plt.plot(x, y)
        plt.draw()
        plt.pause(0.001)
        input("Press [enter] to continue.")

if __name__ == '__main__':
    main()

回答 1


一个对我有用的简单技巧如下:

  1. 在show内使用block = False参数:plt.show(block = False)
  2. 在.py脚本的末尾使用另一个plt.show()

范例

import matplotlib.pyplot as plt

plt.imshow(add_something)
plt.xlabel("x")
plt.ylabel("y")

plt.show(block=False)

#more code here (e.g. do calculations and use print to see them on the screen

plt.show()

注意plt.show()是我脚本的最后一行。


A simple trick that works for me is the following:

  1. Use the block = False argument inside show: plt.show(block = False)
  2. Use another plt.show() at the end of the .py script.

Example:

import matplotlib.pyplot as plt

plt.imshow(add_something)
plt.xlabel("x")
plt.ylabel("y")

plt.show(block=False)

#more code here (e.g. do calculations and use print to see them on the screen

plt.show()

Note: plt.show() is the last line of my script.


回答 2

您可以通过将绘图写入数组,然后在另一个线程中显示该数组来避免阻塞执行。这是一个使用pyformulas 0.2.8中的 pf.screen同时生成和显示图的示例:

import pyformulas as pf
import matplotlib.pyplot as plt
import numpy as np
import time

fig = plt.figure()

canvas = np.zeros((480,640))
screen = pf.screen(canvas, 'Sinusoid')

start = time.time()
while True:
    now = time.time() - start

    x = np.linspace(now-2, now, 100)
    y = np.sin(2*np.pi*x) + np.sin(3*np.pi*x)
    plt.xlim(now-2,now+1)
    plt.ylim(-3,3)
    plt.plot(x, y, c='black')

    # If we haven't already shown or saved the plot, then we need to draw the figure first...
    fig.canvas.draw()

    image = np.fromstring(fig.canvas.tostring_rgb(), dtype=np.uint8, sep='')
    image = image.reshape(fig.canvas.get_width_height()[::-1] + (3,))

    screen.update(image)

#screen.close()

结果:

免责声明:我是pypyulas的维护者。

参考:Matplotlib:将图保存到numpy数组

You can avoid blocking execution by writing the plot to an array, then displaying the array in a different thread. Here is an example of generating and displaying plots simultaneously using pf.screen from pyformulas 0.2.8:

import pyformulas as pf
import matplotlib.pyplot as plt
import numpy as np
import time

fig = plt.figure()

canvas = np.zeros((480,640))
screen = pf.screen(canvas, 'Sinusoid')

start = time.time()
while True:
    now = time.time() - start

    x = np.linspace(now-2, now, 100)
    y = np.sin(2*np.pi*x) + np.sin(3*np.pi*x)
    plt.xlim(now-2,now+1)
    plt.ylim(-3,3)
    plt.plot(x, y, c='black')

    # If we haven't already shown or saved the plot, then we need to draw the figure first...
    fig.canvas.draw()

    image = np.fromstring(fig.canvas.tostring_rgb(), dtype=np.uint8, sep='')
    image = image.reshape(fig.canvas.get_width_height()[::-1] + (3,))

    screen.update(image)

#screen.close()

Result:

Disclaimer: I’m the maintainer for pyformulas.

Reference: Matplotlib: save plot to numpy array


回答 3

这些答案中有很多是超级夸张的,从我的发现中,答案并不是那么难理解。

您可以plt.ion()根据需要使用,但我发现使用plt.draw()同样有效

对于我的特定项目,我正在绘制图像,但是您可以使用plot()scatter()或其他任何一种来代替figimage(),这没关系。

plt.figimage(image_to_show)
plt.draw()
plt.pause(0.001)

要么

fig = plt.figure()
...
fig.figimage(image_to_show)
fig.canvas.draw()
plt.pause(0.001)

如果您使用的是实际数字。
我使用了@ krs013和@Default Picture的答案来解决这个问题,
希望这可以使某人不必在一个单独的线程上启动每个单独的角色,或者不必阅读这些小说就可以解决这个问题。

A lot of these answers are super inflated and from what I can find, the answer isn’t all that difficult to understand.

You can use plt.ion() if you want, but I found using plt.draw() just as effective

For my specific project I’m plotting images, but you can use plot() or scatter() or whatever instead of figimage(), it doesn’t matter.

plt.figimage(image_to_show)
plt.draw()
plt.pause(0.001)

Or

fig = plt.figure()
...
fig.figimage(image_to_show)
fig.canvas.draw()
plt.pause(0.001)

If you’re using an actual figure.
I used @krs013, and @Default Picture’s answers to figure this out
Hopefully this saves someone from having launch every single figure on a separate thread, or from having to read these novels just to figure this out


回答 4

实时绘图

import numpy as np
import matplotlib.pyplot as plt

x = np.linspace(0, 2 * np.pi, 100)
# plt.axis([x[0], x[-1], -1, 1])      # disable autoscaling
for point in x:
    plt.plot(point, np.sin(2 * point), '.', color='b')
    plt.draw()
    plt.pause(0.01)
# plt.clf()                           # clear the current figure

如果数据量太多,您可以通过一个简单的计数器降低更新率

cnt += 1
if (cnt == 10):       # update plot each 10 points
    plt.draw()
    plt.pause(0.01)
    cnt = 0

程序退出后的保持图

这是我的实际问题,无法找到令人满意的答案,我想在脚本完成后未关闭的绘图(例如MATLAB),

如果您考虑一下,在脚本完成后,程序将终止,并且没有逻辑方式以这种方式保存绘图,因此有两个选择

  1. 阻止脚本退出(这是plt.show()而不是我想要的)
  2. 在单独的线程上运行图(太复杂)

这对我来说并不令人满意,所以我在盒子外面找到了另一个解决方案

SaveToFile和在外部查看器中查看

为此,保存和查看均应快速进行,查看器不应锁定文件,而应自动更新内容

选择保存格式

基于矢量的格式既小又快速

  • SVG不错,但是除了默认情况下需要手动刷新的Web浏览器之外,找不到合适的查看器
  • PDF可支持矢量格式,并且有支持实时更新的轻量级查看器

快速实时更新的轻量级查看器

对于PDF,有几个不错的选择

  • 在Windows上,我使用免费,快速,轻巧的SumatraPDF(我的机箱仅使用1.8MB RAM)

  • 在Linux上,有几种选择,例如Evince(GNOME)和Ocular(KDE)

示例代码和结果

用于将绘图输出到文件的示例代码

import numpy as np
import matplotlib.pyplot as plt

x = np.linspace(0, 2 * np.pi, 100)
y = np.sin(2 * x)
plt.plot(x, y)
plt.savefig("fig.pdf")

第一次运行后,在上述其中一个查看器中打开输出文件并欣赏。

这是VSCode和SumatraPDF的屏幕截图,该过程也足够快以达到半实时更新率(我的设置可以time.sleep()在间隔之间使用时接近10Hz )

Live Plotting

import numpy as np
import matplotlib.pyplot as plt

x = np.linspace(0, 2 * np.pi, 100)
# plt.axis([x[0], x[-1], -1, 1])      # disable autoscaling
for point in x:
    plt.plot(point, np.sin(2 * point), '.', color='b')
    plt.draw()
    plt.pause(0.01)
# plt.clf()                           # clear the current figure

if the amount of data is too much you can lower the update rate with a simple counter

cnt += 1
if (cnt == 10):       # update plot each 10 points
    plt.draw()
    plt.pause(0.01)
    cnt = 0

Holding Plot after Program Exit

This was my actual problem that couldn’t find satisfactory answer for, I wanted plotting that didn’t close after the script was finished (like MATLAB),

If you think about it, after the script is finished, the program is terminated and there is no logical way to hold the plot this way, so there are two options

  1. block the script from exiting (that’s plt.show() and not what I want)
  2. run the plot on a separate thread (too complicated)

this wasn’t satisfactory for me so I found another solution outside of the box

SaveToFile and View in external viewer

For this the saving and viewing should be both fast and the viewer shouldn’t lock the file and should update the content automatically

Selecting Format for Saving

vector based formats are both small and fast

  • SVG is good but coudn’t find good viewer for it except the web browser which by default needs manual refresh
  • PDF can support vector formats and there are lightweight viewers which support live updating

Fast Lightweight Viewer with Live Update

For PDF there are several good options

  • On Windows I use SumatraPDF which is free, fast and light (only uses 1.8MB RAM for my case)

  • On Linux there are several options such as Evince (GNOME) and Ocular (KDE)

Sample Code & Results

Sample code for outputing plot to a file

import numpy as np
import matplotlib.pyplot as plt

x = np.linspace(0, 2 * np.pi, 100)
y = np.sin(2 * x)
plt.plot(x, y)
plt.savefig("fig.pdf")

after first run, open the output file in one of the viewers mentioned above and enjoy.

Here is a screenshot of VSCode alongside SumatraPDF, also the process is fast enough to get semi-live update rate (I can get near 10Hz on my setup just use time.sleep() between intervals)


回答 5

Iggy的答案对我来说是最容易遵循的,但是subplot当我执行刚在执行的后续命令时却遇到了以下错误show

MatplotlibDeprecationWarning:当前使用与先前轴相同的参数添加轴将重用较早的实例。在将来的版本中,将始终创建并返回一个新实例。同时,通过向每个轴实例传递唯一的标签,可以抑制此警告,并确保将来的行为。

为了避免此错误,它有助于在用户点击Enter后关闭(或清除)绘图。

这是对我有用的代码:

def plt_show():
    '''Text-blocking version of plt.show()
    Use this instead of plt.show()'''
    plt.draw()
    plt.pause(0.001)
    input("Press enter to continue...")
    plt.close()

Iggy’s answer was the easiest for me to follow, but I got the following error when doing a subsequent subplot command that was not there when I was just doing show:

MatplotlibDeprecationWarning: Adding an axes using the same arguments as a previous axes currently reuses the earlier instance. In a future version, a new instance will always be created and returned. Meanwhile, this warning can be suppressed, and the future behavior ensured, by passing a unique label to each axes instance.

In order to avoid this error, it helps to close (or clear) the plot after the user hits enter.

Here’s the code that worked for me:

def plt_show():
    '''Text-blocking version of plt.show()
    Use this instead of plt.show()'''
    plt.draw()
    plt.pause(0.001)
    input("Press enter to continue...")
    plt.close()

回答 6

Python包drawow允许以非阻塞方式实时更新绘图。
它还可以与网络摄像头和OpenCV配合使用,例如绘制每个帧的度量。
请参阅原始帖子

The Python package drawnow allows to update a plot in real time in a non blocking way.
It also works with a webcam and OpenCV for example to plot measures for each frame.
See the original post.