2017-12-30 58 views
1

私は、2D/3Dのnumpy配列を使ってセルからなるボックスをモデル化しています。細胞はここまでは0から始まる番号を増加させることにより標識され、これは境界を囲む多次元配列の要素のすべての「近傍」を見つけよう

n_cellsボックスは、各次元でなければならないセルの数、基本的に寸法を格納np.arrayある
box = np.arange(np.prod(n_cells)) 
box = box.reshape(n_cells) 

によって行うことができます細胞数を数える。

ここで私の難しい部分は、各セルの隣人を見つけるためのインテリジェントな方法を見つけることです。私の目標は、各セルに隣接する要素を含む配列またはリストを設定することです。理想的には、小さな2Dの例を見てみるのが理想的です。

0: 1, 4, 5, 3, 7, 12, 13, 15 
1: 0, 2, 4, 5, 6, 12, 13, 14 

この方法では、すべての要素が持つように隣人が

0: 1, 4, 5 
1: 0, 2, 4, 5, 6 
2: 1, 5, 6, 7, 3 
... 

しかし、私は、周期的境界条件でそれを持っていると思います周期境界条件なしでここ

0 1 2 3 
4 5 6 7 
8 9 10 11 
12 13 14 15 

、 2Dの8近傍。 理想的には、任意のディメンションに対してこのようなリスト/配列を作成できるようにしたいと思いますが、一般化されたソリューションが利用できない場合は特に2D/3Dに興味があります。

もう1つの問題は、このように、私はすべてのペアを2回カウントします。すなわち、0は1の隣であり、1は0の隣です。これは何か、私はまあ、それは主要な問題ではありません。

+0

このようにします。 https://stackoverflow.com/a/34908879/8881141またはこれですか? https://stackoverflow.com/a/2373689/8881141 – MrT

+0

[ndarrayのセルの隣人を見つける方法]の可能な複製?(https:// stackoverflow。com/questions/34905274/how-to-find-the-n-cell-in-an-ndarray) –

+0

Thx、これは必要な方向に向いていますが、周期性を考慮していません – Marsl

答えて

2

numpy.rollこれは、指定された軸に沿って配列を "ロール"させて、あなたが必要とするものとまったく同じ種類のものにすることができます。例えば、ローリングによって(-1、-1)まで左にすべてをシフトし、その配列は、このように

[[ 5, 6, 7, 4], 
    [ 9, 10, 11, 8], 
    [13, 14, 15, 12], 
    [ 1, 2, 3, 0]] 

になり、私たちはすべてのポイントのための南東の隣人を見つけました。このリスト(ravel)を平坦化し、9つのオフセット(番号自体を意味する(0、0)を含む)のそれぞれについてプロセスを繰り返し、結果を積み重ねます。他のものはその隣接している、最初のエントリは、元の数であり、各行の

[[ 0, 1, 3, 4, 5, 7, 12, 13, 15], 
    [ 1, 2, 0, 5, 6, 4, 13, 14, 12], 
    [ 2, 3, 1, 6, 7, 5, 14, 15, 13], 
    [ 3, 0, 2, 7, 4, 6, 15, 12, 14], 
    [ 4, 5, 7, 8, 9, 11, 0, 1, 3], 
    [ 5, 6, 4, 9, 10, 8, 1, 2, 0], 
    [ 6, 7, 5, 10, 11, 9, 2, 3, 1], 
    [ 7, 4, 6, 11, 8, 10, 3, 0, 2], 
    [ 8, 9, 11, 12, 13, 15, 4, 5, 7], 
    [ 9, 10, 8, 13, 14, 12, 5, 6, 4], 
    [10, 11, 9, 14, 15, 13, 6, 7, 5], 
    [11, 8, 10, 15, 12, 14, 7, 4, 6], 
    [12, 13, 15, 0, 1, 3, 8, 9, 11], 
    [13, 14, 12, 1, 2, 0, 9, 10, 8], 
    [14, 15, 13, 2, 3, 1, 10, 11, 9], 
    [15, 12, 14, 3, 0, 2, 11, 8, 10]] 

dim = len(b.shape)  # number of dimensions 
offsets = [0, -1, 1]  # offsets, 0 first so the original entry is first 
columns = [] 
for shift in itertools.product(offsets, repeat=dim): # equivalent to dim nested loops over offsets 
    columns.append(np.roll(b, shift, np.arange(dim)).ravel()) 
neighbors = np.stack(columns, axis=-1) 

出力(neighborsの値):溶液をアレイbの任意の寸法のために働きます。

あなたはNaNにして、たとえば、冗長なエントリをマスクすることができ、一度だけ記載されている各エントリ隣のペアを持っている:

np.where(neighbors >= neighbors[:, [0]], neighbors, np.nan) 

    [[ 0., 1., 3., 4., 5., 7., 12., 13., 15.], 
    [ 1., 2., nan, 5., 6., 4., 13., 14., 12.], 
    [ 2., 3., nan, 6., 7., 5., 14., 15., 13.], 
    [ 3., nan, nan, 7., 4., 6., 15., 12., 14.], 
    [ 4., 5., 7., 8., 9., 11., nan, nan, nan], 
    [ 5., 6., nan, 9., 10., 8., nan, nan, nan], 
    [ 6., 7., nan, 10., 11., 9., nan, nan, nan], 
    [ 7., nan, nan, 11., 8., 10., nan, nan, nan], 
    [ 8., 9., 11., 12., 13., 15., nan, nan, nan], 
    [ 9., 10., nan, 13., 14., 12., nan, nan, nan], 
    [ 10., 11., nan, 14., 15., 13., nan, nan, nan], 
    [ 11., nan, nan, 15., 12., 14., nan, nan, nan], 
    [ 12., 13., 15., nan, nan, nan, nan, nan, nan], 
    [ 13., 14., nan, nan, nan, nan, nan, nan, nan], 
    [ 14., 15., nan, nan, nan, nan, nan, nan, nan], 
    [ 15., nan, nan, nan, nan, nan, nan, nan, nan]]) 

アイデアがあることneighbors >= neighbors[:, [0]]リストのみセル自体よりも大きな数を持っている人。

+0

商品は少しだけ明確な繰り返しの引数をとります – Eric

+0

どのような美しさ!このような簡潔な方法で探していたことをうまく説明してくれてありがとう。 – Marsl

関連する問題