web-dev-qa-db-ja.com

Excelでの階層的または再帰的なカウント(できればピボットテーブル内)?

階層データセット内、できればピボットテーブル内でデータを集計する方法を見つけようとしていますが、他の方法でも問題ない場合があります。以下のようなデータセット(例では大幅に簡略化されています)について考えてみます。このデータから、次のような質問に答える一連の関数を作成しようとしています。

「フルーツの総在庫はどれくらいありますか?」

「何種類の食べ物を売っていますか?」

Item     Category
=======  ========
Apples   Fruit
Bacon    Meat
Chicken  Meat
Corn     Veg
Food     
Fruit    Food
Grapes   Fruit
Meat     Food
Squash   Veg
Steak    Meat
Veg      Food

Itemには(他の多くの情報の中で)カテゴリがあります、これは本当に「親」と考えることができます。ただし、データセット内では、すべての「親」にも独自の親カテゴリがあることに注意してください。このデータセットでは、階層の1つのサンプル「ブランチ」はFood-> Meat-> Chicken。になります。

「何種類の果物を売っていますか」などの質問に答えるのは難しいことではありません。これは第1レベルのカテゴリだからです。 COUNTIF関数を使用して、「カテゴリ「フルーツ」に属するアイテムはいくつですか?」と言うだけです。 -そして私は次のようなテーブルを取得します:

Item    Category    COUNTIF(categories,me)
Apples  Fruit       0
Bacon   Meat        0
Chicken Meat        0
Corn    Veg         0
Food    Food        3
Fruit   Food        2
Grapes  Fruit       0
Meat    Food        3
Squash  Veg         0
Steak   Meat        0
Veg     Food        2

簡単-最初の行では、「リンゴ」が他の人のカテゴリとして表示される回数が表示されます。 (ゼロなので、Appleが親ではないことはわかっています...これは役立つはずですが、方法はわかりません...)5行目の「Fruit」が他の人のカテゴリとして2回表示されます。はゼロではありません。単なるアイテムではなくカテゴリであることを私は知っています。すべてうまく、最初のレベルの数学には良いですが...

これは私が解決できなかった部分に私を導きます...私が持っている「食べ物」の合計の種類をどのように把握するのですか?そして、私の実際のデータにはさらに多くの階層レベルがあることを考えると、ツリーを上下に歩いて、それぞれに何人の子供がいるかを把握する必要があります。第1レベルのCOUNTIF関数は、食品には3つのサブカテゴリ(果物、野菜、肉)があることを示していますが、私が本当に望んでいるのは、果物、野菜、肉を再帰的に決定することですカテゴリである可能性があり、それらの子に対応する数を合計します。 Excelの用語で言えば、私が本当に望んでいるのは、サブツリー全体のアイテムの総数を再帰的/反復的にカウントする別の列を作成できることです...この場合、Foodに属する7つの固有のアイテムがあります:3つの肉、野菜2個と果物2個。

いくつかの複雑な要因:

  • その特定のアイテムがカテゴリでもあるかどうか、またはそれが最下位のアイテムであるかどうかを示すデータには、明示的識別子はありません。

  • 各アイテムは、そのカテゴリ/親が何であるかを知っているだけです。子があるかどうかを示す明示的なデータはありません。別の言い方をすれば、すべてのアイテムはカテゴリに属しますが、一部のアイテムのみがカテゴリでもあります。

  • 実際のデータでは、親関係は最大10レベルの深さになる可能性がありますが、階層内の各ブランチの深さが一貫しているという保証はありません。一部のアイテムは3レベルの深さで、次のアイテムは8レベルの深さである可能性があります。

  • ルートまたは最終的な親にはカテゴリが付属していませんが、これは1回限りのケースであり、手動で簡単に処理できます。

  • これは「実際の」プログラミング言語(Perl、Pythonなど)では簡単な演習になることを十分に承知しています...しかし、最終的にはプログラミングの経験がない人にこれを渡さなければならないので、私はこれを「標準的な」Excelワークブックに適合させるために非常に懸命に努力しています。

4
ljwobker

最初は、@ Raystafarianに完全に同意しますが、Excelはそのための適切なツールではありません。

ただし、本当にここで実行したい場合は、いくつかのヘルパー列を使用したソリューションを次に示します。

  • level:階層内の実際のアイテムのレベル(ルートアイテムにはレベル1があり、子のレベルは増加します)
    =IFERROR(INDEX([level],MATCH([@Category],[Item],0))+1,1)
  • レベルコード:各アイテムの実行コード、レベル内で一意
    =CHAR(CODE("a")+COUNTIF($C$2:C2,[@level])-1)
  • 長いコード:親とアイテムの連結コード
    =IF([@level]>1,INDEX([long code],MATCH([@Category],[Item],0)),"")&[@[level code]]
  • 子があります:アイテムに子があるかどうかを示すブール値
    =COUNTIF([Category],[@Item])>0

このモデルでは、カテゴリにはすべてのアイテムとサブカテゴリが含まれ、そのコードは親コードと同じシーケンスで始まります(たとえば、fruitのコードがaaの場合、すべての(孫...)子そのうちのaaで始まるコードがあります)

enter image description here

あなたの質問への回答:

「フルーツの総在庫はどれくらいありますか?」

=COUNTIFS(Table1[long code],VLOOKUP(I3,Table1,5,FALSE)&"*",Table1[has child],FALSE)
モデルによると、すべてのアイテムの開始シーケンスは同じです。ここでは、カテゴリではなくアイテムのみを扱っています(2種類の果物applesgrapesを販売していますが、fruitという商品を販売していません)。カテゴリもカウントする場合は、数式の2番目の部分を除外します。

「何種類の食べ物を売っていますか?」

=SUMIF(Table1[long code],VLOOKUP(I10,Table1,5,FALSE)&"*",Table1[inventory])
SUMIFと非常によく似ています

警告

このソリューションには2つの制限があります。

  • 文字数:現在、コードが97のaから始まり、CHAR関数で最後にサポートされる文字は255であるため、どのレベルでも158を超える異なるカテゴリがあります。エラー(最初のコードに小さいコードの文字を使用して少し拡張できます)
  • データベースが増加すると、パフォーマンスが低下する可能性があります(複雑な計算)。計算方法を「データテーブルを除く自動」に設定し、必要なときに手動で計算することをお勧めします。
2
Máté Juhász

マテには良い答えがあると思います。私がそれをする方法はリストであるでしょう:

enter image description here

(すべての配列数式なので、 Ctrl+Shft+Enter

だから、数式(下にドラッグ)

D2 =INDEX($A$2:$A$12,MATCH(0,IF(ISBLANK($B$2:$B$12),COUNTIF($D$1:$D1,$A$2:$A$12),""),0))    
E2 =INDEX($A$2:$A$12,MATCH(0,IF($B$2:$B$12=$D$2,COUNTIF($E$1:$E1,$A$2:$A$12),""),0))
F2 =INDEX($A$2:$A$12,MATCH(0,IF($B$2:$B$12=$E$2,COUNTIF($F$1:$F1,$A$2:$A$12),""),0))
G2 =INDEX($A$2:$A$12,MATCH(0,IF($B$2:$B$12=$E$3,COUNTIF($G$1:$G1,$A$2:$A$12),""),0))
H2 =INDEX($A$2:$A$12,MATCH(0,IF($B$2:$B$12=$E$4,COUNTIF($H$1:$H1,$A$2:$A$12),""),0))

これで、それらを並べ替える方法に応じて、確実に階層を作成したり、ピボットテーブルを使用したりできます。

名前付き範囲で作業できるように、おそらくA列とB列に名前を付けます。

0
Raystafarian