Python函数相当于R中的`pretty()`函数?

9
我正在用Python复制一些R代码。 我遇到了R的 pretty() 函数。 我只需要 pretty(x),其中 x 是一些数字。 大致上,该函数“计算漂亮的断点”,并返回多个“圆”的序列值。我不确定 Python 是否有相应的函数,并且在使用 Google 进行搜索时没有得到很好的结果。
编辑:更具体地说,这是 pretty 函数的 Description 条目:
描述:计算一个大约由 n+1 个等距“圆”值组成的序列,涵盖 x 中值的范围。所选的值是使它们为 10 的幂的 1、2 或 5 倍。
我查看了 R 的 pretty.default() 函数,以确定 R 具体是如何使用该函数的,但最终它使用了 .Internal() -- 通常会导致黑暗的 R 魔法。我想在深入研究之前询问一下周围人的意见。 请问是否有人知道 Python 是否有类似于 R 的 pretty() 函数?

3
以下是需要翻译的内容: C代码:https://svn.r-project.org/R/trunk/src/appl/pretty.c - IRTFM
3
Pandas有cut,NumPy有linspace,但它们不会产生四舍五入的值。 - ayhan
1
@ayhan 我认为最接近的可能是在 matplotlib 绘图时默认的刻度设置行为......不过我还没有找到类似的东西。 - brews
4个回答

12

我觉得Lewis Fogden发布的伪代码很熟悉,我们曾经用C++为绘图例程编写过这个伪代码(以确定漂亮的轴标签)。 我很快将其翻译成Python,不确定这是否类似于R中的pretty(),但我希望它对任何人都有所帮助或有用。

import numpy as np

def nicenumber(x, round):
    exp = np.floor(np.log10(x))
    f   = x / 10**exp

    if round:
        if f < 1.5:
            nf = 1.
        elif f < 3.:
            nf = 2.
        elif f < 7.:
            nf = 5.
        else:
            nf = 10.
    else:
        if f <= 1.:
            nf = 1.
        elif f <= 2.:
            nf = 2.
        elif f <= 5.:
            nf = 5.
        else:
            nf = 10.

    return nf * 10.**exp

def pretty(low, high, n):
    range = nicenumber(high - low, False)
    d     = nicenumber(range / (n-1), True)
    miny  = np.floor(low  / d) * d
    maxy  = np.ceil (high / d) * d
    return np.arange(miny, maxy+0.5*d, d)

例如,这将产生以下结果:

pretty(0.5, 2.56, 10)
pretty(0.5, 25.6, 10)
pretty(0.5, 256, 10 )
pretty(0.5, 2560, 10)
[0.5 1. 1.5 2. 2.5 3.]
[0. 5. 10. 15. 20. 25. 30.]
[0. 50. 100. 150. 200. 250. 300.]
[0. 500. 1000. 1500. 2000. 2500. 3000.]

3

虽然不像R语言那样优雅,但你仍然可以使用numpy:

import numpy as np
np.linspace(a,b,n,dtype=int)

这里的a表示范围的开始,b表示范围的结束,n表示值的数量,输出类型为int

例如:

np.linspace(0,10,11,dtype=int)

数组([ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10])

当然,如果您想让它更加优雅,可以进行包装:

pretty = lambda x: np.linspace(0,x,11,dtype=int)
pretty(10)

1
只有当端点很好时,这才有效... - Michael M

1

这里有一些Python代码,它与R几乎做了相同的事情,除非x范围为零或非常小:

def pretty(x, n):
    """
    Returns a "pretty" set of bin boundaries roughly of size n
    that span x. Use, for instance, like:
      plt.hist(x, bins=pretty(x, 40))
    """
    # see https://github.com/wch/r-source/blob/trunk/src/appl/pretty.c
    h = 1.5
    h5 = .5 + 1.5 * h
    lo = np.nanmin(x)
    up = np.nanmax(x)
    assert up > lo, "All values are the same."
    c = (up - lo) / n
    b = 10 ** np.floor(np.log10(c))
    m = [1, (2+h)/(1+h), (5+2*h5)/(1+h5), (10+5*h)/(1+h), 10]
    k = np.digitize(c/b, m)
    u = b * [1, 2, 5, 10][k-1]
    ns = np.floor(lo / u + 1e-10)
    nu = np.ceil(up / u - 1e-10)
    return np.arange(ns * u, (nu + 1) * u, u)

编辑: 修复了索引错误。


0

numpy.arange是什么?

import numpy as np

print np.arange(0,16,3)

$ [ 0 3 6 9 12 15]


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接