matplotlib:如何使用标记大小/颜色作为绘图中的额外尺寸? [英] matplotlib: How to use marker size / color as an extra dimension in plots?

查看:309
本文介绍了matplotlib:如何使用标记大小/颜色作为绘图中的额外尺寸?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在绘制一个时间序列,其中 x 是一系列 datetime.datetime 对象,而 y 是一系列双打。



我想将标记大小映射到三分之一系列 z (也可能将标记颜色映射到第四系列 w ),这在大多数情况下可以通过:

 散点图(x,y,s = z,c = w)

除了 scatter() 之外,不允许 x 是一系列 datetime.datetime 对象。

  plot(x,y,marker ='o',linestyle ='None')

x datetime.datetime (带有正确的刻度标签)的情况下有效,但是markersize / color只能一次为所有点设置,即无法将它们映射到额外的序列。



看到分散 plot 都可以做一半



UPDATE 之后是



步骤A :来自 datetime matplotlib 约定-兼容 float 用于日期/时间

步骤B :添加 3D | 4D | 5D 功能(使用其他{ color | size | alpha }-信息的编码维)






像往常一样,魔鬼被详细隐藏。



matplotlib 日期等于 几乎 ,但等于:

 #mPlotDATEs.date2num .__ doc__ 

#* d *是类datetime实例或日期时间序列。

#返回值是一个浮点数(或浮点数序列)
#给出自此以来的天数(小数部分表示小时,
#分钟,秒) 0001-01-01 00:00:00 UTC,*加**一个*。
#这里加一个是历史文物。另外,注意
#假定使用公历;这不是通用的
#练习。有关详细信息,请参见模块文档字符串。

因此,强烈建议重新使用其自有工具:


来自matplotlib的导入日期为mPlotDATEs的b

 #辅助函数num2date()
##和date2num()
##进行转换。






管理轴标签&格式化和规模(最小/最大)是一个单独的问题



不过,matplotlib也为您带来了这一方面的武器:



<$来自matplotlib.dates的p $ p> import DateFormatter,\
AutoDateLocator,\
HourLocator,\
MinuteLocator,\
epoch2num $ b来自matplotlib.ticker的$ b导入ScalarFormatter,FuncFormatter

例如,可以这样做:

  aPlotAX.set_xlim(x_min,x_MAX)#X轴限制------------------ -------------------------------------------------- ----------- X-LIMITs 

#lt.gca()。xaxis.set_major_locator(matplotlib.ticker.FixedLocator(secs))
#lt.gca ().xaxis.set_major_formatter(matplotlib.ticker.FuncFormatter(lambda pos,_:time.strftime(%d-%m-%Y%H:%M:%S,time.localtime(pos)))))

aPlotAX.xaxis.set_major_locator(AutoDateLocator())

aPlotAX.xaxis.set_major_formatter(DateFormatter('%Y-%m-%d%H:%M'))#------ -------------------------------------------------- --------------------------------- X-FORMAT

#----- ----------------------------------------#90度x-tick-LABELs

plt.setp(plt.gca()。get_xticklabels(),旋转= 90,
horizo​​ntalalignment ='right'


#- -------------------------------------------------- --------------



添加{ 3D | 4D | 5D }转码



仅是想像这种方法,请查看此示例$ b使用不同的工具将$ b的附加信息维编码为{ color | 大小 | alpha }。而{ size | alpha }与散点相关,对于颜色 matplotlib中还有其他工具包括一组针对各种特定领域或人眼视觉/感知适应的色标进行缩放的着色。在

您可能已经注意到,该 4D 示例仍具有常量 alpha (在真正的 5D 维度可视化中未用于第五个DOF)


I am plotting a time series where x is a series of datetime.datetime objects and y is a series of doubles.

I'd like to map the marker size to a third series z (and possibly also map marker color to a fourth series w), which in most cases could be accomplished with:

scatter(x, y, s=z, c=w)

except scatter() does not permit x being a series of datetime.datetime objects.

plot(x, y, marker='o', linestyle='None')

on the other hand works with x being datetime.datetime (with properly tick label), but markersize/color can only be set for all points at once, namely no way to map them to extra series.

Seeing that scatter and plot each can do half of what I need, is there a way to do both?

UPDATE following @tcaswell's question, I realized scatter raised an KeyError deep in the default_units() in matplotlib/dates.py on the line:

x = x[0]

and sure enough my x and y are both Series taken from a pandas DataFrame which has no '0' in index. I then tried two things (both feel somewhat hacky):

First, I tried modify the DataFrame index to 0..len(x), which led to a different error inside matplotlib/axes/_axes.py at:

offsets  = np.dstack((x,y))

dstack doesn't play nice with pandas Series. So I then tried convert x and y to numpy.array:

scatter(numpy.array(x), numpy.array(y), s=numpy.array(z))

This almost worked except scatter seemed to have trouble auto-scaling x axis and collapsed everything into a straight line, so I have to reset xlim explicitly to see the plot.

All of this is to say that scatter could do the job albeit with a bit of convolution. I had always thought matplotlib can take any array-like inputs but apparently that's not quite true if the data is not simple numbers that require some internal gymnastics.

UPDATE2 I also tried to follow @user3666197's suggestion (thanks for the editing tips btw). If I understood correctly, I first converted x into a series of 'matplotlib style days':

mx = mPlotDATEs.date2num(list(x))

which then allows me to directly call:

scatter(mx, y, s=z)

then to label axis properly, I call:

gca().xaxis.set_major_formatter( DateFormatter('%Y-%m-%d %H:%M'))

(call show() to update the axis label if interactive mode)

It worked quite nicely and feels to me a more 'proper' way of doing things, so I'm going to accept that as the best answer.

解决方案

Is there a way to do both? Yes.

However, lets work by example:

step A: from a datetime to a matplotlib convention-compatible float for dates/times
step B: adding 3D | 4D | 5D capabilities ( using additional { color | size | alpha } --coded dimensionality of information )


As usual, devil is hidden in detail.

matplotlib dates are almost equal, but not equal:

#  mPlotDATEs.date2num.__doc__
#                  
#     *d* is either a class `datetime` instance or a sequence of datetimes.
#
#     Return value is a floating point number (or sequence of floats)
#     which gives the number of days (fraction part represents hours,
#     minutes, seconds) since 0001-01-01 00:00:00 UTC, *plus* *one*.
#     The addition of one here is a historical artifact.  Also, note
#     that the Gregorian calendar is assumed; this is not universal
#     practice.  For details, see the module docstring.

So, highly recommended to re-use their "own" tool:

from matplotlib import dates as mPlotDATEs   # helper functions num2date()
#                                            #              and date2num()
#                                            #              to convert to/from.


Managing axis-labels & formatting & scale (min/max) is a separate issue

Nevertheless, matplotlib brings you arms for this part too:

from matplotlib.dates   import  DateFormatter,    \
                                AutoDateLocator,   \
                                HourLocator,        \
                                MinuteLocator,       \
                                epoch2num
from matplotlib.ticker  import  ScalarFormatter, FuncFormatter

and may for example do:

    aPlotAX.set_xlim( x_min, x_MAX )               # X-AXIS LIMITs ------------------------------------------------------------------------------- X-LIMITs

    #lt.gca().xaxis.set_major_locator(      matplotlib.ticker.FixedLocator(  secs ) )
    #lt.gca().xaxis.set_major_formatter(    matplotlib.ticker.FuncFormatter( lambda pos, _: time.strftime( "%d-%m-%Y %H:%M:%S", time.localtime( pos ) ) ) )

    aPlotAX.xaxis.set_major_locator(   AutoDateLocator() )

    aPlotAX.xaxis.set_major_formatter( DateFormatter( '%Y-%m-%d %H:%M' ) )  # ----------------------------------------------------------------------------------------- X-FORMAT

    #--------------------------------------------- # 90-deg x-tick-LABELs

    plt.setp( plt.gca().get_xticklabels(),  rotation            = 90,
                                            horizontalalignment = 'right'
                                            )

    #------------------------------------------------------------------

Adding { 3D | 4D | 5D } transcoding

Just to imagine the approach, check this example, additional dimensionality of information was coded using different tools into { color | size | alpha }. Whereas { size | alpha } are scatter-point related, for color there are additional tools in matplotlib included a set of colouring scaled for various domain-specific or human-eye vision / perception adapted colour-scales. A nice explanation of color-scale / normalisation scaler is presented here


You may have noticed, that this 4D example still has a constant alpha ( unused for 5th DOF in true 5D dimensionality visualisation )

这篇关于matplotlib:如何使用标记大小/颜色作为绘图中的额外尺寸?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆