web-dev-qa-db-ja.com

NumPy配列のリストを平坦化しますか?

NumPy配列のリスト形式のデータがあるようです(type() = np.ndarray):

[array([[ 0.00353654]]), array([[ 0.00353654]]), array([[ 0.00353654]]), 
array([[ 0.00353654]]), array([[ 0.00353654]]), array([[ 0.00353654]]), 
array([[ 0.00353654]]), array([[ 0.00353654]]), array([[ 0.00353654]]), 
array([[ 0.00353654]]), array([[ 0.00353654]]), array([[ 0.00353654]]),
array([[ 0.00353654]])]

私はこれをpolyfit関数に入れようとしています:

m1 = np.polyfit(x, y, deg=2)

ただし、エラーを返します:TypeError: expected 1D vector for x

データを次のようにフラット化する必要があると思います。

[0.00353654, 0.00353654, 0.00353654, 0.00353654, 0.00353654, 0.00353654 ...]

私は通常リストのリストで機能するリストの理解を試みましたが、これは期待どおりに機能しませんでした:

[val for sublist in risks for val in sublist]

これを行う最良の方法は何でしょうか?

38
Jerry Zhang

numpy.concatenate 。名前が示唆するように、基本的にそのような入力リストのすべての要素を連結して単一のNumPy配列にします。

import numpy as np
out = np.concatenate(input_list).ravel()

最終出力をリストにする場合は、次のようにソリューションを拡張できます-

out = np.concatenate(input_list).ravel().tolist()

サンプル実行-

In [24]: input_list
Out[24]: 
[array([[ 0.00353654]]),
 array([[ 0.00353654]]),
 array([[ 0.00353654]]),
 array([[ 0.00353654]]),
 array([[ 0.00353654]]),
 array([[ 0.00353654]]),
 array([[ 0.00353654]]),
 array([[ 0.00353654]]),
 array([[ 0.00353654]]),
 array([[ 0.00353654]]),
 array([[ 0.00353654]]),
 array([[ 0.00353654]]),
 array([[ 0.00353654]])]

In [25]: np.concatenate(input_list).ravel()
Out[25]: 
array([ 0.00353654,  0.00353654,  0.00353654,  0.00353654,  0.00353654,
        0.00353654,  0.00353654,  0.00353654,  0.00353654,  0.00353654,
        0.00353654,  0.00353654,  0.00353654])

リストに変換-

In [26]: np.concatenate(input_list).ravel().tolist()
Out[26]: 
[0.00353654,
 0.00353654,
 0.00353654,
 0.00353654,
 0.00353654,
 0.00353654,
 0.00353654,
 0.00353654,
 0.00353654,
 0.00353654,
 0.00353654,
 0.00353654,
 0.00353654]
35
Divakar

によっても行うことができます

np.array(list_of_arrays).flatten().tolist()

その結果

[0.00353654, 0.00353654, 0.00353654, 0.00353654, 0.00353654, 0.00353654, 0.00353654, 0.00353654, 0.00353654, 0.00353654, 0.00353654, 0.00353654, 0.00353654]

更新

@aydowがコメントで指摘しているように、numpy.ndarray.ravelの使用は、 copyまたはviewの取得を気にしない場合は高速になる可能性があります

np.array(list_of_arrays).ravel()

ただし、 docs

できるだけ多くの場合にビューが必要な場合は、arr.reshape(-1)が望ましい場合があります。

言い換えると

np.array(list_of_arrays).reshape(-1)

私の最初の提案numpy.ndarray.flattenを使用することで、毎回 がコピーを返す ことでパフォーマンスに影響します。

上記のソリューションの時間の複雑さperfplot OPの1つに類似したセットアップ用のパッケージ

import perfplot

perfplot.show(
    setup=lambda n: np.random.Rand(n, 2),
    kernels=[lambda a: a.ravel(),
             lambda a: a.flatten(),
             lambda a: a.reshape(-1)],
    labels=['ravel', 'flatten', 'reshape'],
    n_range=[2**k for k in range(16)],
    xlabel='N')

enter image description here

ここで、flattenは、初期配列のコピーを、ビューを返すravelおよびreshapeの一定の複雑さと比較することで合理的に説明できる区分的線形複雑を示しています。

予想通り、出力.tolist()を変換すると、3つすべてのパフォーマンスが均等に線形になることも注目に値します。

3
ayorgo

別の簡単なアプローチは、 numpy.hstack() を使用し、続いてsqueeze()のように:

In [61]: np.hstack(list_of_arrs).squeeze()
Out[61]: 
array([0.00353654, 0.00353654, 0.00353654, 0.00353654, 0.00353654,
       0.00353654, 0.00353654, 0.00353654, 0.00353654, 0.00353654,
       0.00353654, 0.00353654, 0.00353654])
2
kmario23

私はこの同じ問題に出くわし、可変長の1次元numpy配列を組み合わせたソリューションを見つけました。

np.column_stack(input_list).ravel()

詳細については、 numpy.column_stack を参照してください。

サンプルデータを使用した可変長配列の例:

In [135]: input_list
Out[135]: 
[array([[ 0.00353654,  0.00353654]]),
 array([[ 0.00353654]]),
 array([[ 0.00353654]]),
 array([[ 0.00353654,  0.00353654,  0.00353654]])]

In [136]: [i.size for i in input_list]    # variable size arrays
Out[136]: [2, 1, 1, 3]

In [137]: np.column_stack(input_list).ravel()
Out[137]: 
array([ 0.00353654,  0.00353654,  0.00353654,  0.00353654,  0.00353654,
        0.00353654,  0.00353654])

注:Python 2.7.12でのみテスト済み

1
zsatter14

配列を平坦化するためにitertoolsを使用する別の方法:

_import itertools

# Recreating array from question
a = [np.array([[0.00353654]])] * 13

# Make an iterator to yield items of the flattened list and create a list from that iterator
flattened = list(itertools.chain.from_iterable(a))
_

このソリューションは、非常にfastおよびmemoryefficientである必要があります。 https://stackoverflow.com/a/408281/5993892 を参照してください。詳細については。

結果のデータ構造がnumpy配列である必要がある場合は、numpy.fromiter()を使用してイテレーターを配列に排出します。

_# Make an iterator to yield items of the flattened list and create a numpy array from that iterator
flattened_array = np.fromiter(itertools.chain.from_iterable(a), float)
_

Docs for itertools.chain.from_iterable()https://docs.python.org/3/library/itertools.html#itertools.chain.from_iterable

Docs for numpy.fromiter()https://docs.scipy.org/doc/numpy/reference/generated/numpy.fromiter.html

0