頭を包むことができなかったことの1つは、Flattenがどのように機能するかです。 2番目の引数として行列が提供されており、 Mathematica のヘルプはこれでは特に良くありません。

Flatten Mathematica のドキュメント:

Flatten[list, {{s11, s12, ...}, {s21, s22, ...}, ...}] 

Flattens listすべてのレベル$ s_ {ij} $を組み合わせて、結果の各レベル$ i $を作成します。

これが実際に何を意味するのか/何をするのかについて誰かが詳しく説明してもらえますか?

回答

One 2番目の引数でFlattenを考える便利な方法は、不規則な(不規則な)リストに対してTransposeのようなものを実行することです。これは簡単です。例:

In[63]:= Flatten[{{1,2,3},{4,5},{6,7},{8,9,10}},{{2},{1}}] Out[63]= {{1,4,6,8},{2,5,7,9},{3,10}} 

何が起こるかは、構成する要素です元のリストのutedレベル1は、結果のレベル2の構成要素になり、その逆も同様です。これはTransposeが行うこととまったく同じですが、不規則なリストに対して行われます。ただし、ここでは位置に関する一部の情報が失われるため、操作を直接逆にすることはできません。

In[65]:= Flatten[{{1,4,6,8},{2,5,7,9},{3,10}},{{2},{1}}] Out[65]= {{1,2,3},{4,5,10},{6,7},{8,9}} 

正しく逆にするために、次のようにします。次のようなことを行うには:

In[67]:= Flatten/@Flatten[{{1,4,6,8},{2,5,7,9},{3,{},{},10}},{{2},{1}}] Out[67]= {{1,2,3},{4,5},{6,7},{8,9,10}} 

より興味深い例は、より深いネストがある場合です:

In[68]:= Flatten[{{{1,2,3},{4,5}},{{6,7},{8,9,10}}},{{2},{1},{3}}] Out[68]= {{{1,2,3},{6,7}},{{4,5},{8,9,10}}} 

ここでも、Flattenが(一般化された)Transposeのように効果的に機能し、最初の2つのレベルでピースを交換していることがわかります。 。以下は理解しにくいでしょう:

In[69]:= Flatten[{{{1, 2, 3}, {4, 5}}, {{6, 7}, {8, 9, 10}}}, {{3}, {1}, {2}}] Out[69]= {{{1, 4}, {6, 8}}, {{2, 5}, {7, 9}}, {{3}, {10}}} 

次の画像は、この一般化された転置を示しています:

循環一般化転置の図

2つの連続したステップで実行できます:

In[72]:= step1 = Flatten[{{{1,2,3},{4,5}},{{6,7},{8,9,10}}},{{1},{3},{2}}] Out[72]= {{{1,4},{2,5},{3}},{{6,8},{7,9},{10}}} In[73]:= step2 = Flatten[step1,{{2},{1},{3}}] Out[73]= {{{1,4},{6,8}},{{2,5},{7,9}},{{3},{10}}} 

順列{3,1,2}{1,3,2}の後に{2,1,3}として取得できます。これがどのように機能するかを確認する別の方法は、数字を使用するichは、リスト構造内の位置を示します。

Flatten[{{{111, 112, 113}, {121, 122}}, {{211, 212}, {221, 222, 223}}}, {{3}, {1}, {2}}] (* ==> {{{111, 121}, {211, 221}}, {{112, 122}, {212, 222}}, {{113}, {223}}} *) 

これから、最も外側のリスト(第1レベル)で、3番目のインデックス(対応する元のリストの3番目のレベル)が大きくなり、各メンバーリスト(2番目のレベル)で最初の要素が要素ごとに大きくなり(元のリストの最初のレベルに対応)、最後に最も内側(3番目のレベル)のリストで2番目のインデックスが大きくなります、元のリストの2番目のレベルに対応します。一般に、2番目の要素として渡されるリストのk番目の要素が{n}の場合、結果のリスト構造でk番目のインデックスを増やすことは、元の構造。

最後に、次のように、複数のレベルを組み合わせてサブレベルを効果的にフラット化できます。

In[74]:= Flatten[{{{1,2,3},{4,5}},{{6,7},{8,9,10}}},{{2},{1,3}}] Out[74]= {{1,2,3,6,7},{4,5,8,9,10}} 

コメント

  • 数字がネストされたリストの元の位置を示していると、’理解しやすいと思います。たとえば、3つの数値の順列の例では、Flatten[{{{111, 112, 113}, {121, 122}}, {{211, 212}, {{221,222,223}}}, {{3},{1},{2}}}になり、結果は{{{111, 121}, {211, 221}}, {{112, 122}, {212, 222}}, {{113}, {223}}}になります。
  • @celtschkありがとう、しかし私は確信していません。私個人としては、視覚的に区別できる番号を追跡し、それらが新しい構造のどこに到達するかを確認する方が簡単です。しかし、これを私の答えに自由に追加してください。これは私にとってはまったく問題ありません。
  • 私たちの理解の仕方はその点でまったく異なっていると思います。実際、自分のやり方を書き直して初めて、巡回置換を完全に理解しました(ただし、後で行った2段階の分解なしで直接)。重要なのは、このようにして、各リストに沿って移動すると、どのインデックスが変更されるかをすぐに確認でき、元のリストを見なくても、リスト構造のどこから番号が発生したかを判断できるということです。言い換えれば、それはより直接的に(少なくとも私には)変換の構造を明らかにします。
  • @celtschkはい、私はあなたの推論を理解しました。しかし、私にとっては、elements ‘インデックスを見るよりも、どの要素がどのリストにジャンプしたかを理解する方が簡単でした。 ‘は私だけかもしれませんが、私は常に代数ではなく幾何学に惹かれていました。どちらの方法にもメリットがあると思います。
  • @LeonidShifrin In[63]:= Flatten[{{1,2,3},{4,5},{6,7},{8,9,10}},{{2},{1}}] Out[63]= {{1,4,6,8},{2,5,7,9},{3,10}}の場合、元のリストのレベル1を構成していた要素が、結果のレベル2。 ‘よくわかりません。入力と出力のレベル構造は同じで、要素は同じレベルのままです。これについて詳しく説明していただけますか?

回答

Flattenの2番目のリスト引数は2つになります目的。まず、要素を収集するときにインデックスが繰り返される順序を指定します。次に、最終結果でのリストのフラット化について説明します。これらの各機能を順番に見ていきましょう。

反復順序

次のマトリックスを検討してください。

$m = Array[Subscript[m, Row[{##}]]&, {4, 3, 2}]; $m // MatrixForm 

マトリックスの結果

使用できますTable式を使用して、すべての要素を反復処理してマトリックスのコピーを作成します。

$m === Table[$m[[i, j, k]], {i, 1, 4}, {j, 1, 3}, {k, 1, 2}] (* True *) 

このID操作は面白くありませんが、反復変数の順序を入れ替えることで配列を変換できます。たとえば、ijを入れ替えることができます。反復子。これは、レベル1とレベル2のインデックスとそれに対応する要素を交換することを意味します。

$r = Table[$m[[i, j, k]], {j, 1, 3}, {i, 1, 4}, {k, 1, 2}]; $r // MatrixForm 

行列の結果

注意深く見ると、元の各要素$m[[i, j, k]]が結果の要素$r[[j, i, k]]-最初の2つのインデックスには蜂がありますn「スワップ」。

Flattenを使用すると、このTable式と同等の操作をより簡潔に表現できます。

$r === Flatten[$m, {{2}, {1}, {3}}] (* True *) 

Flatten式の2番目の引数は、目的のインデックスの順序を明示的に指定します。インデックス1、2、3はインデックス2、1、3になるように変更されました。配列の各次元に範囲を指定する必要がなかったことに注意してください。これは表記上の大きな利便性です。

次のFlattenは、インデックスの順序を変更しないことを指定しているため、ID操作です。

$m === Flatten[$m, {{1}, {2}, {3}}] (* True *) 

次の式は、3つのインデックスすべてを再配置します:1、2 、3-> 3、2、1

Flatten[$m, {{3}, {2}, {1}}] // MatrixForm 

行列の結果

もう一度、インデックス[[i, j, k]]で見つかった元の要素が結果の[[k, j, i]]で見つかることを確認できます。

式、最後に指定されたように、自然な順序で扱われます:

Flatten[$m, {{3}}] === Flatten[$m, {{3}, {1}, {2}}] (* True *) 

この最後の例ではさらに省略します:

Flatten[$m, {3}] === Flatten[$m, {{3}}] (* True *) 

空のインデックスリストはID操作になります:

$m === Flatten[$m, {}] === Flatten[$m, {1}] === Flatten[$m, {{1}, {2}, {3}}] (* True *) 

これにより、反復順序とインデックスのスワッピングが処理されます。それでは、見てみましょう…

リストのフラット化

前の例のサブリストで各インデックスを指定する必要があるのはなぜか疑問に思われるかもしれません。その理由は、インデックス仕様の各サブリストで、結果でどのインデックスを一緒にフラット化するかを指定しているためです。次のID操作についてもう一度検討してください。

Flatten[$m, {{1}, {2}, {3}}] // MatrixForm 

マトリックスの結果

最初の2つのインデックスを同じサブリストに結合するとどうなりますか?

Flatten[$m, {{1, 2}, {3}}] // MatrixForm 

マトリックスの結果

元の結果はペアの4x 3グリッドですが、2番目の結果はペアの単純なリストです。最も深い構造であるペアはそのまま残されています。最初の2つのレベルは1つのレベルにフラット化されています。ソースの3番目のレベルのペアマトリックスは平坦化されないままでした。

代わりに、次の2つのインデックスを組み合わせることができます:

Flatten[$m, {{1}, {2, 3}}] // MatrixForm 

行列の結果

この結果の行数は元の行列と同じです。つまり、最初のレベルは変更されませんでした。ただし、各結果行には、対応する3ペアの元の行から取得した6つの要素のフラットリストがあります。したがって、下位2つのレベルはフラット化されています。

3つのインデックスすべてを組み合わせて、完全にフラット化された結果を取得することもできます。

Flatten[$m, {{1, 2, 3}}] 

マトリックスの結果

これは省略できます:

Flatten[$m, {{1, 2, 3}}] === Flatten[$m, {1, 2, 3}] === Flatten[$m] (* True *) 

Flattenは、インデックススワッピングが行われない場合の省略表記も提供します:

$n = Array[n[##]&, {2, 2, 2, 2, 2}]; Flatten[$n, {{1}, {2}, {3}, {4}, {5}}] === Flatten[$n, 0] (* True *) Flatten[$n, {{1, 2}, {3}, {4}, {5}}] === Flatten[$n, 1] (* True *) Flatten[$n, {{1, 2, 3}, {4}, {5}}] === Flatten[$n, 2] (* True *) Flatten[$n, {{1, 2, 3, 4}, {5}}] === Flatten[$n, 3] (* True *) 

“Ragged”配列

これまでのすべての例では、さまざまな次元の行列を使用しています。 Flattenは、Table式の単なる省略形以上の非常に強力な機能を提供します。 Flattenは、特定のレベルのサブリストの長さが異なる場合を適切に処理します。欠落している要素は静かに無視されます。たとえば、三角配列を反転できます:

$t = Array[# Range[#]&, {5}]; $t // TableForm (* 1 2 4 3 6 9 4 8 12 16 5 10 15 20 25 *) Flatten[$t, {{2}, {1}}] // TableForm (* 1 2 3 4 5 4 6 8 10 9 12 15 16 20 25 *) 

.. ..または裏返して平らにする:

Flatten[$t, {{2, 1}}] (* {1,2,3,4,5,4,6,8,10,9,12,15,16,20,25} *) 

コメント

  • これは素晴らしく徹底的な説明です!
  • @ rm-rfありがとう。 Flattenが一般化されて、インデックスをフラット化(縮小)するときに適用する関数を受け入れる場合、それは”の優れた開始点になると思います。缶内のテンソル代数”。
  • 内部収縮を行う必要がある場合があります。これで、MapFlattenの代わりにFlatten[$m, {{1}, {2, 3}}]を使用してそれを実行できることがわかりました。 Flattenが否定的な議論を受け入れてそれを行うといいでしょう。したがって、このケースはFlatten[$m, -2]のように書くことができます。
  • この優れた回答の得票数がLeonid ‘より少ない理由: (。
  • @Tangshutao プロファイルの2番目のFAQを参照してください。

回答

WReachとLeonidの回答から多くのことを学び、少し貢献したいと思います。

価値があるようですFlattenのリスト値の2番目の引数の主な目的は、特定のレベルのリストをフラット化することだけであることを強調します(WReachがリストの平坦化セクション)。Flattenを不規則なTransposeとして使用することは側面のようです-私の意見では、この主要な設計の効果。

たとえば、昨日、このリストを変換する必要がありました

lists = { {{{1, 0}, {1, 1}}, {{2, 0}, {2, 4}}, {{3, 0}}}, {{{1, 2}, {1, 3}}, {{2, Sqrt[2]}}, {{3, 4}}} (*, more lists... *) }; 

treeform1

これに:

list2 = { {{1, 0}, {1, 1}, {2, 0}, {2, 4}, {3, 0}}, {{1, 2}, {1, 3}, {2, Sqrt[2]}, {3, 4}} (*, more lists... *) } 

treeform2

つまり、2番目と3番目のリストレベルを一緒につぶす必要がありました。

それを行いました

list2 = Flatten[lists, {{1}, {2, 3}}]; 

回答

これは古い質問ですが、ロットの人々。今日、これがどのように機能するかを説明しようとしたときに、非常に明確な説明に出くわしたので、ここで共有することは、より多くの聴衆に役立つと思います。

インデックスの意味>最初に、 index とは何かを明確にします。Mathematicaでは、すべての式はツリーです。たとえば、見てみましょう。リストで:

TreeForm@{{1,2},{3,4}} 

illus1

ツリー内をどのようにナビゲートしますか?

簡単です!ルートから開始し、各交差点でどちらの方向に進むかを選択します。たとえば、ここで2に到達する場合は、 first パス、次に second パスを選択します。この式の要素2の単なるインデックスである{1,2}として書きましょう。

Flattenを理解する方法

完全な表現を提供しない場合は、簡単な質問を検討してください。代わりに、すべての要素とそれらのインデックス、元の式をどのように構築しますか?たとえば、ここで私はあなたに与えます:

{<|"index" -> {1, 1}, "value" -> 1|>, <|"index" -> {1, 2}, "value" -> 2|>, <|"index" -> {2, 1}, "value" -> 3|>, <|"index" -> {2, 2}, "value" -> 4|>} 

そしてすべての頭がListであるとあなたに言うので、何ですか?元の式?

確かに、元の式を{{1,2},{3,4}}として再構築できますが、どうすればよいですか?次の手順をリストできます。

  1. 最初にインデックスの最初の要素を調べ、それによって並べ替えて収集します。次に、 first 式全体の要素には、元のリストの最初の2つの要素が含まれている必要があります…
  2. 次に、2番目の引数を引き続き確認し、同じことを行います…
  3. 最後に、元のリストを{{1,2},{3,4}}として取得します。

まあ、それは合理的です!では、いいえ、最初にインデックスの2番目の要素で並べ替えて収集し、次にインデックスの最初の要素で収集する必要があるとしたらどうでしょうか。または、「2回収集するのではなく、両方の要素で並べ替えるだけで、最初の引数の優先度を高くしますか?

そうですね、それぞれ次の2つのリストが表示されますよね?

  1. {{1,3},{2,4}}
  2. {1,2,3,4}

そうですね、自分で確認してください。Flatten[{{1,2},{3,4}},{{2},{1}}]Flatten[{{1,2},{3,4}},{{1,2}}]も同じです!

では、Flattenの2番目の引数をどのように理解するか?

  1. メインリスト内の各リスト要素(たとえば、{1,2})は、を使用する必要があることを意味します。 GATHER インデックス内のこれらの要素に応じたすべてのリスト、つまりこれらのレベル
  2. リスト要素内の順序は、前の手順でリスト内に収集された要素を SORT する方法を表します。 。たとえば、{2,1}は、第2レベルの位置が第1レベルの位置よりも優先されることを意味します。

では、以前のルールに慣れるための練習をしましょう。

1. Transpose

は、$ A_ {i、j} \ rightarrow A ^ T_ {j、i} $を作成することです。しかし、別の方法で考えることができます。元々は、要素をiインデックスで並べ替えてから、jインデックスで並べ替えます。次に、変更してiインデックスで並べ替えるだけです。 div id = “656e17ee90”> インデックスを最初に作成し、次にiを作成します。したがって、コードは次のようになります。

Flatten[mat,{{2},{1}}] 

単純ですよね?

2。従来のFlatten

単純なm * n行列での従来のフラット化の目標は次のとおりです。 2Dマトリックスの代わりに1D配列を作成します。例:Flatten[{{1,2},{3,4}}]{1,2,3,4}。つまり、今回は要素を収集せずのみを収集します。 を、最初に最初のインデックスで、次に2番目のインデックスで並べ替えます。

Flatten[mat,{{1,2}}] 

3. ArrayFlatten

ArrayFlattenの最も単純なケースについて説明します。ここに、4Dリストがあります:

{{{{1,2},{5,6}},{{3,4},{7,8}}},{{{9,10},{13,14}},{{11,12},{15,16}}}} 

では、このような変換をどのように実行して2Dリストにすることができますか?

$ \ left(\ begin {array} {cc} \ left(\ begin {array} {cc} 1 & 2 \\ 5 & 6 \\ \ end {array} \ right)& \ left(\ begin {array} {cc} 3 & 4 \\ 7 & 8 \\ \ end {array} \ right) \\ \ left(\ begin {array} {cc} 9 & 10 \\ 13 & 14 \\ \ end {array} \ right)& \ left(\ begin {array} {cc} 11 & 12 \\ 15 & 16 \\ \ end {array} \ right)\\ \ end {array} \ right)\ rightarrow \ left(\ begin {array} {cccc} 1 & 2 & 3 & 4 \\ 5 & 6 & 7 & 8 \\ 9 & 10 & 11 & 12 \\ 13 & 14 & 15 & 16 \\ \ end {array} \ right)$

これも簡単です。最初に元の第1レベルと第3レベルのインデックスでグループ化する必要があり、最初のインデックスの優先度を高くする必要があります。並べ替え。同じことが2番目と4番目のレベルにも当てはまります:

Flatten[mat,{{1,3},{2,4}}] 

4。画像の「サイズ変更」

これで画像ができました。例:

img=Image@RandomReal[1,{10,10}] 

しかし、それは間違いなく小さすぎて、ビューなので、各ピクセルを10 * 10サイズの巨大なピクセルに拡張して大きくしたいと思います。

最初に試してみましょう:

ConstantArray[ImageData@img,{10,10}] 

ただし、次元が{10,10,10,10}の4D行列を返します。したがって、Flattenする必要があります。今回は、代わりに3番目の引数の優先度を高くします。最初のものの場合、マイナーな調整が機能します:

Image@Flatten[ConstantArray[ImageData@img,{10,10}],{{3,1},{4,2}}] 

比較:

illus2

これがお役に立てば幸いです!

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です