2016-09-08 9 views
0

は、2つのnumpyサブアレイを1つのものに置き換える簡単なソリューションですが、entireは2つの以前のアレイのエントリに対して呼び出された関数の結果です。例えば:2つのnumpyサブアレイを1つのサブアレイに置き換える方法

f_add(a, b, c, d): 
    return a + b + c + d 

f_sub(b, d): 
    return b-d 

コンクリート

[1, a, b][1, c, d] -> [1, f_add, f_sub] 

:またとして

[1, 0, 50], [1, 3, 1] -> [1, 54, 49] 

、行[1, 0, 50], [1, 3, 1]より大きい配列(例では1行目)の一部であり、それはあるべきです置換されたin-place

([[1, 0, 50], [2, 0, 50], [1, 3.0, 1.0]], 
[[1, 0, 50], [2, 0, 50], [2, 3.0, 1.0]]) 


([[1, 54, 49], [2, 0, 50]], 
[[1, 0, 50], [2, 0, 50], [2, 3.0, 1.0]]) 

ありがとう!

EDIT:

f_add機能とf_subは、私が何をしたいのか説明し、エントリの変更が呼び出される関数の結果であることをするだけの例です。 実際には、(より)意味のある計算を実行するやや複雑な関数を使用します。

第2の点は、この置換は、最初のエントリが同じ要素に対してのみ実行されることです。 したがって、最初の行では[1, 0. 50.][1, 3.0, 1.0]がマージし、2番目の場合は[2, 0., 50.][2, 30, 1.0)となります。

この例では、どのサブアレイがマージするのかを識別する問題を別にしたいと考えましたが、できるだけ一般的なものに含めるべきだと思います。

より完全な例上記1にその結果が以下のようになります:

([[1, 0., 50.], [2, 0., 50], [1, 3.0, 1.0]], 
[[1, 0., 50.], [2, 0., 50.], [2, 3.0, 1.0]]) 

有数の:

([[1, 54., 49.], [2, 0., 50.]], 
[[1, 0., 50.], [2, 54., 49.]]) 
+0

あなたの現在のコードを追加すると素晴らしいでしょう! –

答えて

0

あなたは、この結果を得るために、ジェネレータ式を使用することができます(があると仮定アレイの各要素に対して3つのサブ要素):

ar = ([[1, 0, 50], [2, 0, 50], [1, 3.0, 1.0]], 
     [[1, 0, 50], [2, 0, 50], [2, 3.0, 1.0]]) 
ar = tuple([[[x[0][0], sum(x[0][1:]) + sum(x[-1][1:]), x[0][-1]-x[-1][-1]], x[1]] for x in ar]) 
print ar 

([1、54.0、49.0]、[2]、[0、50]、[1、54.0、49.0]、[2]、[0、50])


EDIT:おそらくより一般的な解決策として、配列の要素に対して望ましい計算を実行し、その関数を配列のすべての行にマップする関数f(x)を定義することができます。例えば、

def f(x): 
    if (x[0][0] == x[1][0]): 
     return [[x[0][0], x[0][1]+x[0][2]+x[1][1]+x[1][2], x[0][2]-x[1][2]], x[2]] 
    elif (x[0][0] == x[2][0]): 
     return [[x[0][0], x[0][1]+x[0][2]+x[2][1]+x[2][2], x[0][2]-x[2][2]], x[1]] 
    elif (x[1][0] == x[2][0]): 
     return [x[0], [x[1][0], x[1][1]+x[1][2]+x[2][1]+x[2][2], x[1][2]-x[2][2]]] 
    else: 
     return x 

ar = ([[1, 0, 50], [2, 0, 50], [1, 3.0, 1.0]], 
     [[1, 0, 50], [2, 0, 50], [2, 3.0, 1.0]]) 

print tuple(map(f, ar)) 

([1、54.0、49.0]、[2]、[0、50]、[1、0、50]、[2、54.0、49.0])

+0

私はおそらく関数f_addとf_subは、私がやりたいことを説明するための単なる例であり、現実には意味のある計算を行うやや複雑な関数を使っています。 もう1つは、この置換は、最初のエントリが同じ要素に対してのみ実行されることです。 したがって、最初の行で[1,050.]と[2,0.50.]のみがマージされ、2番目の行では[2,0.50.]と[2,30.000] 。 – vare

+0

ああ、そうです。私は問題を誤解した。おそらく 'map(f、ar)'を使ってすべての行に関数をマップし、その関数内でロジックを実装することができますか?それを達成するためのより良い方法があるかもしれませんが(そのうちの私は知らない)。 – PyNoob

+0

これはかなりエレガントに見えます。私は先験的に長さを知らないため、ハードコードされた添え字を使うことができない配列の関数をより汎用的にすると思います。 – vare

0

配列に多くの機能がある場合は、かなり複雑に思えるかもしれません。私は関数呼び出しを少し簡潔に管理するクラスに各行を分割することを検討します。これにより

def merge(a,b): 
    res = [a[0]] # test b[0] is same? 
    abcd = a[1:]+b[1:] # list join 
    # use np.concatenate here is a,b are arrays 
    res.append(f_add(*abcd)) 
    res.append(f_sum(a[2],b[2])) 
    return res 
def f_add(a,b,c,d): 
    return a+b+c+d 
def f_sum(b,d): 
    return b-d 

In [484]: merge([1,0,50],[1,3,1]) 
Out[484]: [1, 54, 49] 

class Row: 
    def __init__(self, row): 
     self.row = row 

     self.sum1 = None 
     self.sub1 = None 

     self._add(row) 
     self._sub(row) 

    def _add(self, items): 
     self.sum1 = sum([items[0][1], items[0][2], items[-1][1], items[-1][2]]) 

    def _sub(self, items): 
     self.sub1 = items[0][2] - items[-1][2] 

    def update(self): 
     self.row = [[self.row[0][0], self.sum1, self.sub1], self.row[1]] 

# Data 
arr = ([[1, 0, 50], [2, 0, 50], [1, 3.0, 1.0]], 
[[1, 0, 50], [2, 0, 50], [2, 3.0, 1.0]]) 

# Usage 
for row in arr: 
    r = Row(row) 
    print r.sum1, r.sub1 

    r.update() 
    print r.row 



>>> 54.0 49.0 
    [[1, 54.0, 49.0], [2, 0, 50]] 
    54.0 49.0 
    [[1, 54.0, 49.0], [2, 0, 50]] # This row doesnt match your example, but you get the idea 
0

はここ2つの入力がリストされていると仮定すると、最初の(最も内側の)ステップを実行するための機能です。たとえば、あなたは、クラス内の関連する機能のすべてを含めることができます要素の混合使用、および一般的な機能の場合、これらを配列として扱う点はあまりありません。

次に、同じx[0]のリストがマージされるリストのリストである 'row'を処理する関数を記述します。一致するペアを収集する最も簡単な方法は、defaultdictです。

私はペアを見つける。上記の関数でマージします。

def subs(alist): 
    # collect the matching ids 
    from collections import defaultdict 
    dd = defaultdict(list) 
    for i,x in enumerate(alist): 
     dd[x[0]].append(x) 
    # merge pairs 
    for i in dd.keys(): 
     if len(dd[i])==2: 
      dd[i]=merge(dd[i][0],dd[i][1]) 
     elif len(dd[i])==1: 
      dd[i]=dd[i][0] # flatten 
     else: 
      pass # do nothing with triplets etc. 
    return list(dd.values()) 

In [512]: lll= [[[1, 0, 50], [2, 0, 50], [1, 3.0, 1.0]], 
    ...: [[1, 0, 50], [2, 0, 50], [2, 3.0, 1.0]]] 

In [513]: [subs(l) for l in lll] 
Out[513]: [[[1, 54.0, 49.0], [2, 0, 50]], 
      [[1, 0, 50], [2, 54.0, 49.0]]] 

lllが3D配列に変換することができます

In [523]: arr=np.array(lll) 
In [524]: arr 
Out[524]: 
array([[[ 1., 0., 50.], 
     [ 2., 0., 50.], 
     [ 1., 3., 1.]], 

     [[ 1., 0., 50.], 
     [ 2., 0., 50.], 
     [ 2., 3., 1.]]]) 

と私たちはミックスとマッチしたいのIDは以下のとおりです。マージされる

In [525]: arr[:,:,0] 
Out[525]: 
array([[ 1., 2., 1.], 
     [ 1., 2., 2.]]) 

ペアが

です
In [526]: arr[0,[0,2],:] 
Out[526]: 
array([[ 1., 0., 50.], 
     [ 1., 3., 1.]]) 

と2合併:

In [527]: merge(*arr[0,[0,2],:].tolist()) 
Out[527]: [1.0, 54.0, 49.0] 
In [528]: merge(*arr[1,[1,2],:].tolist()) 
Out[528]: [2.0, 54.0, 49.0] 

しかし、これらのペアを識別していない、と合併を実行し、新しい配列を構築することは、それがリストにあったより配列で何も容易です。

In [532]: np.array([subs(l.tolist()) for l in arr]) 
Out[532]: 
array([[[ 1., 54., 49.], 
     [ 2., 0., 50.]], 

     [[ 1., 0., 50.], 
     [ 2., 54., 49.]]]) 
関連する問題