4

次のように定義された 3D 複雑な numpy 配列があります。

> import numpy as np
> a = np.random.rand(2,3,4) + np.random.rand(2,3,4) * 1j
> a
array([[[ 0.40506245+0.68587874j,  0.74700976+0.73208816j,
      0.42010818+0.31124884j,  0.27181199+0.54599156j],
    [ 0.29457621+0.34057513j,  0.82490182+0.63943948j,
      0.46887722+0.12734375j,  0.77184637+0.21522095j],
    [ 0.67774944+0.8208908j ,  0.41476702+0.85332392j,
      0.10084665+0.56146324j,  0.71325041+0.77306548j]],

   [[ 0.77843387+0.23660274j,  0.23671262+0.63997834j,
      0.60831419+0.41741288j,  0.53870756+0.13747055j],
    [ 0.12477767+0.54603678j,  0.60537090+0.89208227j,
      0.16027151+0.17575777j,  0.18801875+0.27282324j],
    [ 0.82308271+0.97238411j,  0.47458327+0.75200695j,
      0.16085009+0.60620705j,  0.79766571+0.76470634j]]])

少しMATLABに似た特定の形式の文字列に出力する必要があり s、私が見つけた最良の方法は次のとおりです:(私にとって、形式を説明する最良の方法はこのコードを使用することです)

> s = ''
> for k in range(a.shape[2]):
>   for j in range(a.shape[1]):
>     for i in range(a.shape[0]):
>       s += str(a[i,j,k].real) + ' '
>   for j in range(a.shape[1]):
>     for i in range(a.shape[0]):
>       s += str(a[i,j,k].imag) + ' '

私にはあまり「pythonic」に見えないこのコードに満足していません (私は C++ 出身で、Python についてあまり知りません)。Python には、ここで使用できる優れた構文 (たとえば、リストの内包表記など) が用意されていると確信していますが、あまり詳しくありません。

したがって、私の質問は次のとおりです。このコードをよりpythonicに改善するにはどうすればよいですか?

編集:この 3D 配列は、2 行 3 列の複素行列の配列として表示されます。この形式は、最初の行列の実部、次に虚部を出力し、各行列に対してそのように反復することで構成されます。

これは、MATLAB でこのコードを実行したときに得られる形式です。

> a = rand(2,3,4) + rand(2,3,4) * 1i;
> s = sprintf('%g %g ', [real(a) imag(a)]);

私の主な目標は、このフォーマットと互換性を持つことです。

4

2 に答える 2

3

文字列の連結は通常、 join を使用して行われます。

s += str(a[i,j,k].imag) + ' '

で置き換えることができます

s += ' '.join(str(a[i,j,k].imag))

グローバルに適用されるワンライナーは次のようになります。

s = ' '.join(' '.join(str(a[i,j,k].real) for j in range(a.shape[1]) for i in range(a.shape[0])) + ' ' + ' '.join(str(a[i,j,k].imag) for j in range(a.shape[1]) for i in range(a.shape[0])) for k in range(a.shape[2]))

はっきりしない。for ... k ループを保持し、次のように記述します。

s = ''
for k in range(a.shape[2]):
    s += ' '.join(str(a[i,j,k].real) for j in range(a.shape[1]) for i in range(a.shape[0]))
    s += ' '
    s += ' '.join(str(a[i,j,k].imag) for j in range(a.shape[1]) for i in range(a.shape[0]))
    s += ' '

編集

これはかなり重く、numpy には多くのツールがあります。これは、より単純なバージョンです。最初の行は、2 行目の作業を容易にするために行列を再フォーマットします。

b = [numpy.vstack((a.real.T[i], a.imag.T[i])) for i in range(a.shape[2])]
s = ' '.join(str(d) for x in b for d in x.flat)

編集 2

まだ簡略化できる

' '.join([str(x) for x in np.hstack((a.T.real, a.T.imag)).flat])
于 2013-06-03T14:32:47.737 に答える
1

十分に考えれば、中間コピーの作成を回避できるはずです。しかし、人生は短いので、どうですか?

' '.join(np.hstack([a.T.real, a.T.imag]).astype(str).flat)

例えば:

>>> a
array([[[ 0.75878533+0.6450401j ,  0.97544304+0.95294337j,
          0.72619451+0.70150035j,  0.53653874+0.72336166j],
        [ 0.44497093+0.59486404j,  0.48346416+0.602289j  ,
          0.89508307+0.10804834j,  0.60925276+0.78463914j],
        [ 0.75324059+0.35750314j,  0.77764455+0.52714092j,
          0.60422248+0.45825998j,  0.06100151+0.98814297j]],

       [[ 0.25167445+0.26036597j,  0.14479218+0.63888545j,
          0.69195476+0.65571239j,  0.75384667+0.35208925j],
        [ 0.33299320+0.95810933j,  0.28706287+0.92696162j,
          0.80174074+0.73461441j,  0.64070651+0.95546677j],
        [ 0.32726129+0.28131131j,  0.84847281+0.0043481j ,
          0.20002495+0.92129643j,  0.85657582+0.17598515j]]])
>>> new = ' '.join(np.hstack([a.T.real, a.T.imag]).astype(str).flat)
>>> new
'0.758785326622 0.251674447258 0.444970928938 0.332993197954 0.753240586102 0.3272612899 0.645040097487 0.260365974319 0.59486403781 0.958109327206 0.357503144442 0.281311309104 0.975443036171 0.14479217684 0.483464161328 0.287062874161 0.777644547623 0.84847280757 0.952943365086 0.638885451204 0.602289004931 0.926961617163 0.527140924938 0.00434810439813 0.726194510838 0.691954756116 0.895083070782 0.801740737909 0.604222482831 0.200024953365 0.701500350108 0.655712387542 0.108048340908 0.734614410363 0.458259975834 0.921296429741 0.536538738872 0.75384667023 0.609252761053 0.640706514463 0.0610015096191 0.856575822125 0.723361662643 0.35208924756 0.784639135069 0.955466768932 0.988142972679 0.175985147504'
>>> original(a).strip() == new
True

更新:.astype(str)何らかの理由で機能しない場合は、フォールバックとして:

>>> new2 = ' '.join(map(str, np.hstack([a.T.real, a.T.imag]).flat))
>>> original(a).strip() == new2
True
于 2013-06-03T15:21:37.730 に答える