Изменить способ печати структурированных массивов и массивов

Numpy суммирует большие arrays, что удобно при работе в интерактивном сеансе. К сожалению, структурированный arrays а также recarrays не суммированы очень хорошо по умолчанию. Есть ли способ изменить это?

По умолчанию полный array отображается, если есть 1000 или меньше элементов. Когда есть больше предметов, чем это array суммируется. Это может быть установлено с np.set_printoptions(threshold=<number of items to trigger summarization>, edgeitems=<number of items to show in summary>), Это прекрасно работает для стандартных типов данных, например:

np.set_printoptions(threshold=3, edgeitems=1)
print(np.zeros(3))
print(np.zeros(4))

результаты в

[ 0.  0.  0.]
[ 0. ...,  0.]

Тем не менее, когда используются более сложные типы данных, обобщение менее полезно

print(np.zeros(4, dtype=[('test', 'i4', 3)]))
print(np.zeros(4, dtype=[('test', 'i4', 4)]))

[([0, 0, 0],) ..., ([0, 0, 0],)]
[([0, 0, 0, 0],) ..., ([0, 0, 0, 0],)]

Массив суммируется, но подтипы - нет. Это становится проблемой с большим arrays используя сложные типы данных. Например, arraynp.zeros(1000, dtype=[('a', float, 3000), ('b', float, 10000)]) вешает мой экземпляр ipython.

Есть несколько обходных путей, а не использование np.array Напечатайте напрямую, это можно создать подкласс и написать собственный __repr__, Это будет работать для больших проектов, но не решает основную проблему и не удобно для быстрого исследования данных в интерактивном сеансе Python. Я также реализовал пользовательский фильтр в своем редакторе, который усекает очень длинный вывод на консоль. Это что-то вроде хака и не помогает, когда я запускаю сеанс Python в другом месте.

Есть ли какая-то непонятная настройка, о которой я не знаю, или настройка python или ipython, которая может это исправить?

1 ответ

Вот обходной путь, который я нашел, который позволяет разумно распечатывать массивы записей.

def count_dtype(dtype):
    """
    dtype : datatype descr (list of strings / tuples, subdtypes rather than dtype object)
    Return total number of elements in array of dtype
    """
    sum = 0
    for name, t, *shape in dtype:
        if isinstance(t, str): ## base datatype
            if shape:
                sum += np.multiply.reduce(shape[0], dtype=np.int64)
            else:
                sum += 1
        else: ## Subarray type
            sum += np.multiply.reduce(shape, dtype=np.int64)*count_dtype(t)
    return sum


def _recarray2string(a, options, separator=' ', prefix=""):
    """
    Create a string representation of a record array
    a : record array
    separator : used by _array2string
    prefix : used by _array2string
    """
    options = np.get_printoptions()
    threshold = options['threshold']
    edgeitems = options['edgeitems']

    size = count_dtype(a.dtype.descr)
    items = np.multiply.reduce(a.shape)
    if size*items > threshold/(2*edgeitems): ## Too big
        if size > threshold: ## subtype is too large - how to handle?
            newopt = options.copy()
            newopt['threshold'] = options['threshold'] // (2*options['edgeitems'])
            def fmt_subtype(r):
                res = []
                for sub in r:
                    if sub.dtype.names is not None:
                        res.append(fmt_subtype(sub))
                    else:
                        res.append(_array2string(sub, newopt, separator=separator, prefix=prefix))
                return separator.join(res)
            return separator.join(fmt_subtype(a[i]) for i in range(edgeitems)) + '\n...\n' + \
                   separator.join(fmt_subtype(a[a.shape[0]-i-1]) for i in range(edgeitems))
        else: ## Subtype is small enough it's sufficient to truncate only sub-dtype
            options = options.copy()
            options['threshold'] = threshold // size
            return _array2string_old(a, options, separator=separator, prefix=prefix)
    else:  ## Print as normal
        return _array2string_old(a, options, separator=separator, prefix=prefix)


def _array2string(a, options , separator=' ', prefix=""):
    """
    monkeypatched print function that allows truncating record arrays sensibly
    """
    if a.dtype.names is not None:
        return  _recarray2string(a, options, separator=separator, prefix=prefix)
    else:
        return _array2string_old(a, options, separator=separator, prefix=prefix)


# Setup monkeypatching
_array2string_old = np.core.arrayprint._array2string
np.core.arrayprint._array2string = _array2string
Другие вопросы по тегам