【问题标题】:making matplotlib graphs look like R by default?默认情况下使matplotlib图看起来像R?
【发布时间】:2012-12-30 05:16:28
【问题描述】:

有没有办法让matplotlib 在绘制默认值方面表现得与 R 相同,或者几乎像 R?例如,R 对待它的轴与matplotlib 完全不同。以下直方图

具有带有向外刻度的“浮动轴”,因此没有内部刻度(与matplotlib 不同)并且轴不会“靠近”原点交叉。此外,直方图可以“溢出”到未由刻度标记的值 - 例如x 轴在 3 处结束,但直方图稍微超出它。如何为matplotlib 中的所有直方图自动实现这一点?

相关问题:散点图和折线图在 R 中具有不同的默认轴设置,例如:

不再有内壁虱,壁虱朝外。此外,刻度在原点(y 轴和 x 轴在坐标轴左下角交叉处)之后稍微开始,并且刻度在坐标轴结束之前稍微结束。这样,最低 x 轴刻度和最低 y 轴刻度的标签就不能真正交叉,因为它们之间有一个空间,这使绘图看起来非常优雅干净。请注意,轴刻度标签和刻度本身之间也有相当大的空间。

此外,默认情况下,未标记的 x 或 y 轴上没有刻度,这意味着与右侧标记的 y 轴平行的左侧 y 轴没有刻度,x -axis,再次从图中消除混乱。

有没有办法让 matplotlib 看起来像这样?通常默认情况下看起来与默认 R 图一样多?我非常喜欢matplotlib,但我认为 R 默认值/开箱即用的绘图行为确实让事情变得正确,它的默认设置很少导致重叠的刻度标签、混乱或压扁的数据,所以我想要默认值尽可能做到这一点。

【问题讨论】:

  • 考虑 matplotlib 可以做XKCD-style,这应该是某人在公园里散步! :)
  • @AndyHayden:我同意,但我认为目前还没有任何模板可以提供 R 风格的绘图!此处提供的示例仅模拟一两个图,但一般不能解决问题。默认的 matplotlib 设置根本不起作用。如果我可以补充一点,这将比 XKCD 样式的绘图更有用(并且可能更容易实现!)。
  • “R 风格”的全局设置将非常有用,遗憾的是 300rep 似乎没有足够的广告来找人做。祝你好运。
  • @AndyHayden:公平地说,这对我来说是一项艰巨的任务,但我认为 1000 个代表点不会有所作为……不知道该怎么做。它要么比我想象的要困难,要么人们对此并不感兴趣(我很确定是后者)

标签: python r matplotlib plot pandas


【解决方案1】:

一年后编辑:

使用seaborn,下面的例子变成:

import numpy as np
import matplotlib.pyplot as plt
import seaborn
seaborn.set(style='ticks')
# Data to be represented
X = np.random.randn(256)

# Actual plotting
fig = plt.figure(figsize=(8,6), dpi=72, facecolor="white")
axes = plt.subplot(111)
heights, positions, patches = axes.hist(X, color='white')
seaborn.despine(ax=axes, offset=10, trim=True)
fig.tight_layout()
plt.show()

很简单。

原帖:

这篇博文是我迄今为止看到的最好的。 http://messymind.net/making-matplotlib-look-like-ggplot/

它不像您在大多数“入门”类型的示例中看到的那样专注于您的标准 R 图。相反,它试图模仿 ggplot2 的风格,这似乎几乎被普遍认为是时尚和精心设计的。

要获得如您在条形图中看到的轴刺,请尝试遵循此处的前几个示例之一:http://www.loria.fr/~rougier/coding/gallery/

最后,要使轴刻度线指向外部,您可以编辑您的 matplotlibrc 文件,将其设置为 xtick.direction : outytick.direction : out

将这些概念结合在一起,我们会得到这样的结果:

import numpy as np
import matplotlib
import matplotlib.pyplot as plt
# Data to be represented
X = np.random.randn(256)

# Actual plotting
fig = plt.figure(figsize=(8,6), dpi=72, facecolor="white")
axes = plt.subplot(111)
heights, positions, patches = axes.hist(X, color='white')

axes.spines['right'].set_color('none')
axes.spines['top'].set_color('none')
axes.xaxis.set_ticks_position('bottom')

# was: axes.spines['bottom'].set_position(('data',1.1*X.min()))
axes.spines['bottom'].set_position(('axes', -0.05))
axes.yaxis.set_ticks_position('left')
axes.spines['left'].set_position(('axes', -0.05))

axes.set_xlim([np.floor(positions.min()), np.ceil(positions.max())])
axes.set_ylim([0,70])
axes.xaxis.grid(False)
axes.yaxis.grid(False)
fig.tight_layout()
plt.show()

可以通过多种方式指定刺的位置。如果您在 IPython 中运行上述代码,则可以执行 axes.spines['bottom'].set_position? 以查看所有选项。

是的。这不是微不足道的,但你可以接近。

【讨论】:

  • 这可以做网格,但几乎没有做上面概述的任何轴...它的刻度看起来也很有趣。
  • 我认识的 3 个使用 R 的人,使用 ggplot2 制作数字,所以这似乎与我有关。要了解情况,请在此处查看前几个示例:loria.fr/~rougier/coding/gallery。他们至少应该让你走上正确的道路。
  • ggplot2 很好,但我主要指的是 R 基础。虽然 ggplot2 看起来很时尚,但您可以说这种背景色网格会导致打印时大量浪费墨水等。此外,许多使用 R 的人经常只使用没有 ggplot2 的 R 基础,所以我的目标是让 matplotlib 看起来像比 ggplot2 更通用的 R 基础。
  • 您引用的页面中的示例loria.fr/~rougier/coding/gallery/spine/spines-5.py 最接近条形图轴,但仍然与它有很大不同......它看起来被切碎了,不像直方图的默认浮动轴在 R 中绘图。不想挑剔,只是说即使具有强大的自定义能力,我仍然不清楚如何使轴看起来像直方图中的那些轴,这是 R 中的默认行为。
  • 谢谢,但这些set_position 调用取决于数据限制。有没有办法为任意数据自动化它?
【解决方案2】:

matplotlib >= 1.4 支持 styles(并且内置了 ggplot 样式):

In [1]: import matplotlib as mpl

In [2]: import matplotlib.pyplot as plt

In [3]: import numpy as np

In [4]: mpl.style.available
Out[4]: [u'dark_background', u'grayscale', u'ggplot']

In [5]: mpl.style.use('ggplot')

In [6]: plt.hist(np.random.randn(100000))
Out[6]: 
...

【讨论】:

【解决方案3】:

# # # # # #

编辑 2013 年 10 月 14 日: 有关信息,现在已经为 python 实现了 ggplot(基于 matplotlib)。

查看此blog 或直接转至项目的github page 以获取更多信息和示例。

# # # # # #

据我所知,matplotlib 中没有内置解决方案可以直接为您的图形提供与使用 R 制作的图形相似的外观。

一些包,比如mpltools,使用 Matplotlib 的 rc 参数添加了对样式表的支持,并且可以帮助您获得 ggplot 外观(参见ggplot style 的示例)。

但是,由于一切都可以在 matplotlib 中进行调整,因此您可能更容易直接开发自己的函数来实现您想要的功能。例如,下面是一个 sn-p,可让您轻松自定义任何 matplotlib 绘图的轴。

def customaxis(ax, c_left='k', c_bottom='k', c_right='none', c_top='none',
               lw=3, size=20, pad=8):

    for c_spine, spine in zip([c_left, c_bottom, c_right, c_top],
                              ['left', 'bottom', 'right', 'top']):
        if c_spine != 'none':
            ax.spines[spine].set_color(c_spine)
            ax.spines[spine].set_linewidth(lw)
        else:
            ax.spines[spine].set_color('none')
    if (c_bottom == 'none') & (c_top == 'none'): # no bottom and no top
        ax.xaxis.set_ticks_position('none')
    elif (c_bottom != 'none') & (c_top != 'none'): # bottom and top
        ax.tick_params(axis='x', direction='out', width=lw, length=7,
                      color=c_bottom, labelsize=size, pad=pad)
    elif (c_bottom != 'none') & (c_top == 'none'): # bottom but not top
        ax.xaxis.set_ticks_position('bottom')
        ax.tick_params(axis='x', direction='out', width=lw, length=7,
                       color=c_bottom, labelsize=size, pad=pad)
    elif (c_bottom == 'none') & (c_top != 'none'): # no bottom but top
        ax.xaxis.set_ticks_position('top')
        ax.tick_params(axis='x', direction='out', width=lw, length=7,
                       color=c_top, labelsize=size, pad=pad)
    if (c_left == 'none') & (c_right == 'none'): # no left and no right
        ax.yaxis.set_ticks_position('none')
    elif (c_left != 'none') & (c_right != 'none'): # left and right
        ax.tick_params(axis='y', direction='out', width=lw, length=7,
                       color=c_left, labelsize=size, pad=pad)
    elif (c_left != 'none') & (c_right == 'none'): # left but not right
        ax.yaxis.set_ticks_position('left')
        ax.tick_params(axis='y', direction='out', width=lw, length=7,
                       color=c_left, labelsize=size, pad=pad)
    elif (c_left == 'none') & (c_right != 'none'): # no left but right
        ax.yaxis.set_ticks_position('right')
        ax.tick_params(axis='y', direction='out', width=lw, length=7,
                       color=c_right, labelsize=size, pad=pad)

编辑:对于非接触式脊椎,请参阅下面的函数,该函数会导致脊椎位移 10 pts(取自 matplotlib 网站上的 this example)。

def adjust_spines(ax,spines):
    for loc, spine in ax.spines.items():
        if loc in spines:
            spine.set_position(('outward',10)) # outward by 10 points
            spine.set_smart_bounds(True)
        else:
            spine.set_color('none') # don't draw spine

例如,下面的代码和两张图向您展示了 matplotib 的默认输出(左侧),以及调用函数时的输出(右侧):

import numpy as np
import matplotlib.pyplot as plt

fig,(ax1,ax2) = plt.subplots(figsize=(8,5), ncols=2)
ax1.plot(np.random.rand(20), np.random.rand(20), 'ok')
ax2.plot(np.random.rand(20), np.random.rand(20), 'ok')

customaxis(ax2) # remove top and right spines, ticks out
adjust_spines(ax2, ['left', 'bottom']) # non touching spines

plt.show()

当然,您需要花费一些时间来确定必须在 matplotlib 中调整哪些参数以使您的图看起来与 R 的图完全一样,但我不确定现在还有其他选择。

【讨论】:

  • 如何获得“浮动”轴,尽管它们不接触,如直方图示例中所示?右边的东西实际上从未由 R
  • 请参阅 matplotlib 网站上的 this example 以了解 matplotlib 中的非接触式脊椎
  • @user248237 我已经编辑了响应以包含非接触脊椎的功能。也请参阅更新的图。希望对您有所帮助。
【解决方案4】:

我会查看Bokeh,它旨在“在 R 中提供与 ggplot 相当的引人注目的 Python”。示例here

编辑:还可以查看Seaborn,它试图重现 ggplot2 的视觉风格和语法。

【讨论】:

  • 我在您显示的链接中没有看到任何示例?但即使没有例子,基于 R 书的图形语法看起来比我上面提到的任何简单的面包和黄油图都要复杂得多
【解决方案5】:

这是一篇您可能有兴趣阅读的博文:

Pandas GSoC2012 绘图

http://pandasplotting.blogspot.com/

决定尝试实现一个ggplot2类型的绘图接口...目前还不确定要实现多少ggplot2功能...

作者 fork pandas 并为 pandas 构建了很多 ggplot2 风格的语法。

plot = rplot.RPlot(tips_data, x='total_bill', y='tip')
plot.add(rplot.TrellisGrid(['sex', 'smoker']))
plot.add(rplot.GeomHistogram())
plot.render(plt.gcf())

pandas 分叉在这里:https://github.com/orbitfold/pandas

似乎制作受 R 影响的图形的代码位于一个名为 rplot.py 的文件中,该文件可以在 repo 的一个分支中找到。

class GeomScatter(Layer):
    """
    An efficient scatter plot, use this instead of GeomPoint for speed.
    """

class GeomHistogram(Layer):
    """
    An efficient histogram, use this instead of GeomBar for speed.
    """

分支链接:

https://github.com/orbitfold/pandas/blob/rplot/pandas/tools/rplot.py

我觉得这真的很酷,但我不知道这个项目是否正在维护。最后一次提交是在不久前。

【讨论】:

    【解决方案6】:

    Setting spines in matplotlibrc 解释了为什么不能简单地编辑 Matplotlib 默认值来生成 R 风格的直方图。对于散点图, R style data-axis buffer in matplotlibIn matplotlib, how do you draw R-style axis ticks that point outward from the axes? 显示了一些默认值,可以更改这些默认值以提供更 R-ish 的外观。在其他一些答案的基础上,假设您在 Axes 实例上使用 facecolor='none' 调用了 hist(),以下函数可以很好地模仿 R 的直方图样式。

    def Rify(axes):
        '''
        Produce R-style Axes properties
        '''
        xticks = axes.get_xticks() 
        yticks = axes.get_yticks()
    
        #remove right and upper spines
        axes.spines['right'].set_color('none') 
        axes.spines['top'].set_color('none')
    
        #make the background transparent
        axes.set_axis_bgcolor('none')
    
        #allow space between bottom and left spines and Axes
        axes.spines['bottom'].set_position(('axes', -0.05))
        axes.spines['left'].set_position(('axes', -0.05))
    
        #allow plot to extend beyond spines
        axes.spines['bottom'].set_bounds(xticks[0], xticks[-2])
        axes.spines['left'].set_bounds(yticks[0], yticks[-2])
    
        #set tick parameters to be more R-like
        axes.tick_params(direction='out', top=False, right=False, length=10, pad=12, width=1, labelsize='medium')
    
        #set x and y ticks to include all but the last tick
        axes.set_xticks(xticks[:-1])
        axes.set_yticks(yticks[:-1])
    
        return axes
    

    【讨论】:

      【解决方案7】:

      Seaborn 可视化库可以做到这一点。例如,要重现 R 直方图的样式,请使用:

      sns.despine(offset=10, trim=True)
      

      https://seaborn.pydata.org/tutorial/aesthetics.html#removing-axes-spines

      要重现 R 散点图的样式,请使用:

      sns.set_style("ticks")
      

      https://seaborn.pydata.org/tutorial/aesthetics.html#seaborn-figure-styles所示

      【讨论】:

        【解决方案8】:

        import matplotlib.pyplot as plt plt.style.use('ggplot')

        在这里做一些情节,并享受它

        【讨论】:

          猜你喜欢
          • 2021-10-17
          • 1970-01-01
          • 1970-01-01
          • 2012-02-29
          • 2011-11-12
          • 2016-11-30
          • 1970-01-01
          • 2011-10-18
          • 2014-08-21
          相关资源
          最近更新 更多