1

Numpy は大きなarraysをまとめたもので、インタラクティブなセッションで作業するときに便利です。残念ながら、構造化されており、デフォルトarraysrecarraysはうまく要約されていません。これを変更する方法はありますか?

デフォルトでは、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これは、複雑なデータ型を大量に使用する場合に問題になります。たとえばarray np.zeros(1000, dtype=[('a', float, 3000), ('b', float, 10000)])、ipython インスタンスがハングアップします。

np.arrayタイプを直接使用するのではなく、サブクラス化して custom を作成することで、いくつかの回避策があります__repr__。これは大規模なプロジェクトでは機能しますが、根本的な問題は解決されず、インタラクティブな Python セッションでデータをすばやく探索するには不便です。また、非常に長いコンソール出力を切り捨てるカスタム フィルターをエディターに実装しました。これはちょっとしたハックで、別の場所で Python セッションを開始するときには役に立ちません。

私が知らないnumpy設定、またはこれを修正できるpythonまたはipython設定はありますか?

4

1 に答える 1

0

これは、レコード配列の賢明な印刷を可能にする、私が思いついた回避策です。

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
于 2018-08-31T15:46:50.767 に答える