[[20100324150116]] 『配列数式とINDEX関数の使い方を教えて』(おいちゃん) ページの最後に飛ぶ

[ 初めての方へ | 一覧(最新更新順) | 全文検索 | 過去ログ ]

 

 『配列数式とINDEX関数の使い方を教えて』(おいちゃん)

 配列数式の勉強をしているものですが、『エクセルの学校』の問題に対して下記のような数式を考えましたが答えが全く違って出てきます。
INDEX関数は数式を配列数式に変換する関数だと理解していたのですが(もちろん本来のインデックス関数としての用法もありますが)、今回のことで配列数式が全くわかっていなかったと感じています。
 A1:B10の表に対してC1の配列数式は正しい答えを出しますが、C2,C3,C4のINDEX関数を使った数式ではそれぞれ違って間違った結果が出てきます。INDEX関数の位置を変えただけですが本来の用法と違うのでしょうか?INDEX関数の正しい使い方・用法をご存知の方詳しい説明をお願いいたします。

 また、C2,C3,C4の数式をD1,E1,F1に入力するとまた違った答えになります。これは共通部分参照機能とかが原因かもしれませんがその仕組みもよくわかりません。併せて教えていただけたらありがたいです。ちなみにINDEXを使った数式もCtrl+Shift+Enterで正しい答えになります。(こんな無駄なことは誰もしないでしょうけど)

      A      B     C

 1	a	x	3	{=COUNT(1/(MATCH($A$1:$A$10,IF($B$1:$B$10="x",$A$1:$A$10,),)=ROW($A$1:$A$10)))}

 2	b		0	=COUNT(INDEX(1/(MATCH($A$1:$A$10,IF($B$1:$B$10="x",$A$1:$A$10,),)=ROW($A$1:$A$10)),))

 3	c	x	1	=COUNT(1/INDEX(MATCH($A$1:$A$10,IF($B$1:$B$10="x",$A$1:$A$10,),)=ROW($A$1:$A$10),))

 4	a	x	5	=COUNT(INDEX(1/(MATCH($A$1:$A$10,IF($B$1:$B$10="x",$A$1:$A$10,),)=ROW($A$1:$A$10)),))

 5	c		0	=INDEX(COUNT(1/(MATCH($A$1:$A$10,IF($B$1:$B$10="x",$A$1:$A$10,),)=ROW($A$1:$A$10))),)

 6	d

 7	b

 8	e	x

 9	a	x

 10	c

 −−−−

もともとの問題である『エクセルの学校』の質問番号を書き忘れていました。

[[20071226153821]] 『重複しないデータの合計数』(ureahoy) です。

よろしくお願いします。(おいちゃん)


 ◆式をこのようにしてください
 =COUNT(INDEX(1/(MATCH(A1:A10&"x",A1:A10&B1:B10,0)=ROW($1:$10)),))
 (Maron)


 >今回のことで配列数式が全くわかっていなかったと感じています。 
 配列数式が完全に分かっている人もいないです。
 関数を開発したプログラマーは別でしょうが・・・

 一言で言うなら、誰であっても、最後の所は、実際にやってみて確かめるしかないンです。
 回答者は、経験で色々知っているだけです。(理詰めで会得したのではなく、いじくり回して会得したのです)

 >INDEX関数は数式を配列数式に変換する関数だと理解していたのですが
 字句上の意味はおくとして、云いたいことは分かります。
 上述しました通り、そんな単純な理屈ではないです。

 IF関数は、条件式を配列にした時点で配列数式(CSE数式)になります。Indexに神通力はありません。
 (例外は無視するものとします。変な突っ込みがあると面倒なので、この一文を入れておきます)

 >また、C2,C3,C4の数式をD1,E1,F1に入力するとまた違った答えになります。
 CSE入力をしなければ、普通の数式なので、数式入力行と同じ位置にあるデータで真偽判定されてしまいます。

 つまり、一行目に下式を入力するのであれば、
 >D1セル =COUNT(INDEX(1/(MATCH($A$1:$A$10,IF($B$1:$B$10="x",$A$1:$A$10,),)=ROW($A$1:$A$10)),))
 >E1セル =COUNT(1/INDEX(MATCH($A$1:$A$10, IF($B$1:$B$10="x",$A$1:$A$10,),)=ROW($A$1:$A$10),))

 下式と同じ意味でしかないと云うことです。
   D1セル =COUNT(INDEX(1/(MATCH($A$1:$A$10,IF($B$1   ="x",$A$1:$A$10,),)=ROW($A$1:$A$10)),))
   E1セル =COUNT(1/INDEX(MATCH($A$1:$A$10, IF($B$1   ="x",$A$1:$A$10,),)=ROW($A$1:$A$10),))

 ※ 2行目に入力なら、下式と同じ意味
   D2セル =COUNT(INDEX(1/(MATCH($A$1:$A$10,IF($B$2      ="x",$A$1:$A$10,),)=ROW($A$1:$A$10)),))
   E2セル =COUNT(1/INDEX(MATCH($A$1:$A$10, IF($B$2      ="x",$A$1:$A$10,),)=ROW($A$1:$A$10),))

 (半平太) 2010/03/24 20:09

 お礼が遅くなってしまいすみません。
 Maronさん、いつもながらのスマートな解答ありがとうございます。私は質問コーナーへの投稿は今回が初めてですが、
 Maronさんの様なシンプルで正確な数式を自分の発想で考えられたらいいなと関数の勉強をしています。

 半平太さん、詳しく説明くださりありがとうございます。
 IF関数はINDEX関数を使ってもCSE入力をしないと共通部分参照機能が働いて入力行の真偽判定しかしないことを知りました。
 (CSEという言葉もはじめて知りました)
 それでC2、C5、C5などの”x”の無い、つまりIF関数で偽の判定をする行ではINDEXをどこに使った数式でも答えが0になってしまうんですね。
 ただIF関数で真の判定をするC1,C3,C4などの行では、同じ行でも(つまりD1,E1,F1,やD3,E3,F3などに)INDEX関数の入力位置を変えただけで
 答えが違ってくることの理由がまだわかりません。
(INDEXをCOUNT関数の前においた時=1,”1/”の前においた時=5、MATCH関数の前においた時=1、IF関数の前においた時=0となります)
 ただし、いずれの場合もF9で数式バーを見ると答えは正しい”3”となっております。
 COUNT関数の場合、実際の計算結果と数式バーでの計算過程とが違っていたことは今までもあり疑問に思っておりましたが、
 こうなるとINDEXをどこに入れるかを正しく知らないと、いくつものパターンで検証しない限り正しい関数式が導き出せないことになり
 安心できません。

 INDEX関数の持つ機能を正しく理解し使いたいと思いますが、半平太さんのおっしゃるように
 みんな試行錯誤で経験しながら身に付けてきたというのであれば、
 誰かそれをマニュアルとして本にでもしてもらえるとありがたいのですが・・・。
 それとも中途半端にINDEX関数を使わずにCSE入力で数式を入力するほうが無難なのか・・・。
 すいませんその辺のアドバイスも頂けるとありがたいです。(おいちゃん)


 A1:A10に数値・文字等を入れ

 =count(A1:A10) 
 =count(1/A1:A10)
 の結果を確認してみましょう

 論理演算の場合、数式入力行と同じ位置にあるデータで真偽判定されてしまいます

 INDEX関数の位置により、COUNT関数に配列を返すか、値を返すのかが変わってきます

 =COUNT(1/INDEX(A1:A10,))
 は 下段と同じように配列ではなく論理演算を返しています

 編集 17:20
 下の方の指摘通りですね
 「論理演算」を 「演算」に訂正します

 配列数式の中で、AND,OR関数を使用すると期待する値にならない
 (厳密に言えばある規則に従った値となるわけですが)ので
 AND,OR関数の変わりに論理演算等を使用して回避します

 INDEX関数は配列を返しますが、中でIF関数を使用すると期待する値になりません
 数値であれば論理演算を使用したり、一工夫する必要があります
 この場合は、(Maron)さん回答のようにするといいですね

 COUNT関数の中で演算処理等を行った配列を配列として扱わないようです
 と言うことを言いたかったのです

 名無しより

 ↑
 都度、署名するルールが明確にされておりますので、ご協力をお願いします。

 ところで『1/A1:A10』のどこが論理演算なのですか?

 >CSEという言葉もはじめて知りました
 ヘルプにこう書いてあるので、流用しました。
      ↓
 『配列数式をブックに入力するときは Ctrl キーと Shift キーを押しながら 
  Enter キーを押すため、配列数式は "CSE 数式" とも呼ばれます。』

 『CSE入力』は短く書こうと勝手に造語しました。(^^ゞ

 > IF関数はINDEX関数を使ってもCSE入力をしないと共通部分参照機能が働いて入力行の真偽判定しかしないことを知りました。
 「共通部分参照機能」ってなんなのか、私は分かりません。m(__)m

 > ただIF関数で真の判定をするC1,C3,C4などの行では、同じ行でも(つまりD1,E1,F1,やD3,E3,F3などに)INDEX関数の入力位置を変えただけで
 > 答えが違ってくることの理由がまだわかりません。
 >(INDEXをCOUNT関数の前においた時=1,”1/”の前においた時=5、MATCH関数の前においた時=1、IF関数の前においた時=0となります)
 > ただし、いずれの場合もF9で数式バーを見ると答えは正しい”3”となっております。
 > COUNT関数の場合、実際の計算結果と数式バーでの計算過程とが違っていたことは今までもあり疑問に思っておりましたが、
 > こうなるとINDEXをどこに入れるかを正しく知らないと、いくつものパターンで検証しない限り正しい関数式が導き出せないことになり
 > 安心できません。

 C3セル =COUNT(   1/INDEX(MATCH($A$1:$A$10,IF($B$1:$B$10="x",$A$1:$A$10,),)=ROW($A$1:$A$10),))
 C4セル =COUNT(INDEX(1/(   MATCH($A$1:$A$10,IF($B$1:$B$10="x",$A$1:$A$10,),)=ROW($A$1:$A$10)),))

 C3セルのCOUNTは、直接INDEXから配列を貰うことを要求しているのに、
 その前段階で(分母の配列に)INDEXでラップされても効果ないってことです。

 こうやれば、C4と同じ「5」は得られます。・・・と云っても正解の「3」にはなりませんので無駄な抵抗です。
  ↓
 C3セル =COUNT(INDEX(1/INDEX(MATCH($A$1:$A$10,IF($B$1:$B$10="x",$A$1:$A$10,),)=ROW($A$1:$A$10),),0))

 IFを使う限り、役には立ちません。

 >誰かそれをマニュアルとして本にでもしてもらえるとありがたいのですが・・・。
 >それとも中途半端にINDEX関数を使わずにCSE入力で数式を入力するほうが無難なのか・・・。

 かなりINDEXにこだわってらっしゃいますが、IFを使おうが使わまいが、配列数式はCSE入力すべきなのです。

 回答者は、初心者が上手く入力できない事が少なくないので、そのフォローが面倒なため、
 普通入力できる方策として採用した意味合いが強いです。誤解を恐れずに云えば邪道なんです。

 本に書いても、実需はないと思います。
 マイクロソフトにこのINDEXの使いかたを解説してくれ、と云っても、
 恐らくキョトンとされるだけだと思います。
 何故に、CSE入力しないの? ってことになるでしょう。

 (半平太) 2010/03/27 16:31

 半平太さん早速のお返事ありがとうございます。

 「エクセルの学校」で関数の勉強をしているとシンプルでスマートな回答をされている方々が、
皆さんINDEX関数をスマートに使いこなされているのを見て、
上達するにはINDEX関数をマスターしなければと勝手に思い込んでおりました。
 私自身はINDEX関数を使うために8文字も余分に入力するより一発で入力できるCSE入力の方が
簡単だとは思っていたので少し安心いたしました。
これからは自信を持ってCSE入力を使って行きたいと思います。
 
 はっきりした事は
 INDEXは、配列をほしい関数の引数の位置におくということ、
 IF関数は、CSE入力しないとINDEXを使っても配列として機能しないで関数入力行のみの真偽判定をするということの二つは分かりました。

 だだ、配列の理解の為に教えてもらいたいのですが、C4のINDEXの位置で答えが"5"になる理由は分かりませんか?
 数式入力行のみで真偽判定をするということは、正解の"3"より小さい"1"や"0"に答えがなるなら原因も考えられるのですが、
多くなるということは何か別の作用・機能が働いているような気がします。ただのCOUNT関数との相性でしょうか。  

 それとCOUNT関数だけでしょうか、F9で見る数式バーでの計算結果とセルに表示される答えが違う関数は?
どこでどういう配列に変換されているのかを知る一番の方法だったのですが。
 よろしくお願いいたします。

 最後になりましたが、(無名)さん、
 >COUNT関数の中で演算処理等を行った配列を配列として扱わないようです
は大変貴重なアドバイスでした。ありがとうございます。
(おいちゃん)

 数式がどの様に計算しているか知りたい場合は
 メニュー・ツール(T)→ワークシート分析(U) 数式の検証(F)
 を開いてみると良いかもしれません。

 4行目に入れた
=COUNT(INDEX(1/(MATCH($A$1:$A$10,IF($B$1:$B$10="x",$A$1:$A$10,),)=ROW($A$1:$A$10)),))
 の数式は
 B4セルが x なので、IF関数の条件を満たします。
 よって
 =COUNT(INDEX(1/(MATCH($A$1:$A$10,$A$1:$A$10,)=ROW($A$1:$A$10)),))
 こんな式での計算がされています。

  数式の検証で確認すると
  =COUNT(INDEX(1/MATCH({"a";"b";"c";"a";"c";"d";"b";"e";"a";"c"},$A$1:$A$10,)=ROW($A$1:$A$10)),))
  と表示されますが。

 A1:A10には、a,b,c,d,e の 5種類の文字が有るので
 C2セルにはその種類の数が表示されています。

 (HANA)

 > 数式入力行のみで真偽判定をするということは、正解の"3"より小さい"1"や"0"に答えがなるなら原因も考えられるのですが、

 一つの行で真偽判定されると云うことはご理解頂いたと思います。

 すると「x」がある行に数式が入力されれば、IF関連は「真」としか判定されなくなります。
 つまり、全行に「x」が入力されているのと同じことになり、 5種類と云う値が返るのです。

 (半平太) 2010/03/28 19:09

 回答が重複しますが、せっかく書いたので・・・
 こんな感じかな

 C2=COUNT(INDEX(1/(MATCH($A$1:$A$10,IF($B$1:$B$10="x",$A$1:$A$10,),)=ROW($A$1:$A$10)),))

 IF関数について考えてみると
 2行目ですので  
 =COUNT(INDEX(1/(MATCH($A$1:$A$10,IF($B$2="x",$A$1:$A$10,),)=ROW($A$1:$A$10)),))
 IF($B$1:$B$10="x",$A$1:$A$10,) の結果は 0 となりますので
 =COUNT(INDEX(1/(MATCH($A$1:$A$10,0,),)=ROW($A$1:$A$10)),))
 MATCH($A$1:$A$10,0,)はすべて#N/Aと言う配列を返すことになります
 {#N/A;#N/A;#N/A;#N/A;#N/A;#N/A;#N/A;#N/A;#N/A;#N/A}

 同様に1,3,4行目に入力されている場合
 IF($B$1:$B$10="x",$A$1:$A$10,) の結果は $A$1:$A$10 となりますので
 =COUNT(INDEX(1/(MATCH($A$1:$A$10,$A$1:$A$10,),)=ROW($A$1:$A$10)),))
 配列数式を理解していれば 5 になることを理解できますよね

 一方     1/INDEX の場合
 =COUNT(1/INDEX(MATCH($A$1:$A$10,IF($B$1:$B$10="x",$A$1:$A$10,),)=ROW($A$1:$A$10),))

 IF関数について考えてみると
 2行目など "x"が入力されていない場合
 =COUNT(1/INDEX(MATCH($A$1:$A$10,0,),)=ROW($A$1:$A$10),))
 COUNT関数は演算したもの(数式等により計算によって導き出された配列)を配列として扱いません
 演算した配列の最初の値を返します
 =COUNT(1/(MATCH($A$1,0,)=ROW($A$1)))     ・・・・ 0

 1,3,4行目のように  "x"が入力されている場合
 =COUNT(1/INDEX(MATCH($A$1:$A$10,$A$1:$A$10,),)=ROW($A$1:$A$10),))
 COUNT関数は演算したものを配列として扱いません
 演算した配列の最初の値を返します
 =COUNT(1/(MATCH($A$1,$A$1:$A$10,)=ROW($A$1)))  ・・・・ 1

 名無しより

 編集 PM12:00
 検証不足でしたので上記の記載は無視してください
 (今回提示された式の場合、上記のような処理をしているようですが・・・)

 =COUNT(A1:A10*5)    ・・・ 直接セル参照し演算した場合
 この場合、IF関数と同じように入力するセル位置に左右されるようです。

 =COUNT({1;2;"s";4;5}*3)     ・・・・直接配列を入力し演算した場合
 この場合は、正常に認識するようです

 SUM,MAX関数も同じような動作をするようですね?

 皆さん、ありがとうございました。大感激です。
 
 半平太さんの
 >「x」がある行に数式が入力されれば、IF関連は「真」としか判定されなくなります。
  つまり、全行に「x」が入力されているのと同じことになり、
 は、今までIF関数以下では数式入力行が「x」のある行のとき、その行のA列の値だけが返ると考えていたので
 計算結果が理解できませんでした。
  $A$1:$A$10という配列というか範囲すべてが返ってくるとは思いもしませんでした。
 でも条件が一つだけでその結果がTrueの訳ですから当然といえば当然ですよね。納得です。

 名無しさんの
  >=COUNT(A1:A10*5)    ・・・ 直接セル参照し演算した場合
 この場合、IF関数と同じように入力するセル位置に左右されるようです。
 SUM,MAX関数も同じような動作をするようですね?
 は、COUNT関数が演算したものを配列として扱わない場合、配列の最初の値を使うのか数式の入力行の値を使うのかと考え、
 頭が一層混乱しておりましたが関数の決まりが分かり計算推移が見えるようになりました。

 HANAさんに教えていただいた「数式の検証」は本当に役立ちました。エクセルにこんな心配りのできた機能があったのは驚きです。
 また、この検証ではCOUNT関数をF9で見たときのような関数結果との誤差もありませんし、今後も関数の解析に活躍してくれそうです。

皆さん今後ともよろしくお願い致します。(おいちゃん)


コメント返信:

[ 一覧(最新更新順) ]


YukiWiki 1.6.7 Copyright (C) 2000,2001 by Hiroshi Yuki. Modified by kazu.