Comptage hiérarchique ou récursif dans Excel (de préférence dans un tableau croisé dynamique)?

4

J'essaie de trouver un moyen d'agréger les données dans un ensemble de données hiérarchique, de préférence dans un tableau croisé dynamique, mais d'autres méthodes pourraient également convenir. Considérons un ensemble de données (grandement simplifié pour l'exemple) qui ressemble à celui ci-dessous. À partir de ces données, j'essaie de créer un ensemble de fonctions qui répondront à des questions telles que:

"Quel est l'inventaire total pour Fruit?"

"Combien de types d'aliments puis-je vendre?"

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

Chaque Article a (parmi beaucoup d'autres informations) un Catégorie , que nous pouvons vraiment considérer comme un "parent". Mais notez également que dans l’ensemble de données, tous les «parents» ont également leurs propres catégories de parents. Dans cet ensemble de données, un échantillon de 'branche' de la hiérarchie serait Aliments & Viande & Poulet.

Pour répondre à la question du type "Combien de sortes de fruits puis-je vendre?", Ce n'est pas difficile, car c'est la catégorie de premier niveau. Je peux simplement utiliser la fonction COUNTIF et dire "Combien d'articles appartiennent à la catégorie" Fruits "?" - et je reçois une table qui ressemble à ceci:

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

Facile - pour la première ligne, vous voyez seulement combien de fois "Pommes" apparaît dans la catégorie de quelqu'un d'autre. (Puisqu'il est égal à zéro, je sais que les pommes ne sont pas un parent ... cela devrait aider, mais je ne sais pas comment ...) Maintenant, la cinquième ligne, "Fruit", apparaît comme la catégorie de quelqu'un d'autre à deux reprises - depuis le nombre n'est pas nul, je sais que c'est une catégorie plutôt qu'un élément. Tout va bien pour les mathématiques de premier niveau, mais ...

Cela m'amène à la partie que je n'ai pas pu résoudre ... Comment puis-je déterminer le nombre total de types de "nourriture" que j'ai? Et étant donné que mes données réelles comportent beaucoup plus de niveaux de hiérarchie, je dois parcourir l’arbre pour déterminer le nombre total d’enfants dans chacun d’eux. La fonction COUNTIF du premier niveau me dit qu'il existe trois sous-catégories d'aliments (fruits, légumes et viande) - mais ce que je veux vraiment, c'est de le faire déterminer de manière récursive que les fruits, les légumes et la viande pourrait aussi être Catégories, et résumez les nombres correspondants pour ces enfants. En termes excellents, ce que je veux vraiment, c’est pouvoir construire une autre colonne qui compte de manière récursive / itérative le nombre TOTAL d’éléments de cette sous-arborescence ... 2 légumes et 2 fruits.

Quelques facteurs de complication:

  • Il n'y a pas explicite identifiant dans les données pour nous dire si cet élément particulier est également une catégorie, ou si c'est un niveau inférieur article.

  • Chaque élément ne connaît que sa catégorie / son parent - il n’existe aucune donnée explicite permettant de savoir s’il a ou non des enfants. En d'autres termes: tous les éléments appartiennent à une catégorie, mais seuls certains éléments sont également des catégories.

  • Dans les données réelles, la relation parent peut aller jusqu'à 10 niveaux profonds, MAIS il n’ya aucune garantie que la profondeur de chaque la branche dans la hiérarchie est cohérente: certains éléments peuvent avoir 3 niveaux profond tandis que le prochain pourrait être 8.

  • La racine ou le parent ultime ne vient pas avec une catégorie, mais c'est un cas unique que je peux facilement gérer manuellement.

  • Je suis tout à fait conscient du fait que ce serait un exercice trivial dans n'importe quel langage de programmation (réel, Perl, Python, etc.) ... essayant très très fort de faire en sorte que cela rentre dans un classeur Excel "standard".

ljwobker
la source
Avez-vous regardé (avez-vous accès à) Power Pivot? Je ne l'ai pas dans 365/2016, mais c'était un complément gratuit inclus dans certaines versions d'Excel et qui permettait de créer des hiérarchies. Je ne sais pas si cela répondra à vos besoins, mais cela pourrait valoir le coup.
Ron Rosenfeld
1
Il ne me semble pas qu'Excel soit le bon outil pour ce travail.
Raystafarian
RonRosenfeld- J'ai ceci, mais il ne semble pas faire ce dont j'ai besoin ... @Raystafarian: Je suis tout à fait d'accord (comme je l'ai dit, il est trivial de coder comme une promenade récursive dans quoi que ce soit d'autre) et je Je l'ai déjà codé en Python, mais au final, je ne le maintiens pas et l'écrasante majorité des AUTRES objets dont j'ai besoin de cette application / classeur / quoi que vous fassiez sont idéaux dans Excel. C'était la "dernière chose" que j'essayais de faire fonctionner nativement dans Excel ...
ljwobker
1
Est-ce que l'accès MS est une possibilité? Je veux dire, avec la structure de vos données, cela serait même une tâche difficile avec VBA dans Excel. Est-il possible de modifier la structure de données? Ou pour savoir quelles catégories il y a toujours, comme un rapport assez statique?
Raystafarian
@Raystafarian Il existe un bon nombre "d'autres" moyens de le résoudre - mais je suis un peu dans cet étrange coin où je peux l'obtenir résolu à 100% en "standard, portable, non-VBA" excellent ... ou Je dois avoir QUELQUES autres types d'applications externes ou d'aide ... Et si je dois suivre cette voie, ce sera juste Python (puisque je l'ai déjà écrit). Malheureusement, dans ce cas précis, la seule valeur incrémentielle réelle est si je peux le faire de manière native dans un classeur Excel 'normal' ...
ljwobker

Réponses:

2

Au début, je suis entièrement d'accord avec @Raystafarian, Excel n'est pas le bon outil pour cela.

Cependant, si vous voulez vraiment le faire ici, voici une solution avec quelques colonnes d'assistance:

  • level: niveau de l'élément actuel dans la hiérarchie (les éléments principaux ont le niveau 1, le niveau des enfants est augmenté)
    =IFERROR(INDEX([level],MATCH([@Category],[Item],0))+1,1)
  • code de niveau: code courant pour chaque article, unique WITHIN LEVELS
    =CHAR(CODE("a")+COUNTIF($C$2:C2,[@level])-1)
  • code long: code concaténé du parent & amp; article
    =IF([@level]>1,INDEX([long code],MATCH([@Category],[Item],0)),"")&[@[level code]]
  • a enfant: booléen indiquant si l'objet a un enfant
    =COUNTIF([Category],[@Item])>0

Avec ce modèle, une catégorie contient tous les articles et sous-catégories dont le code commence par la même séquence que le code parent (par exemple, si fruit Le code de aa, alors tous les (grands ...) enfants ont un code commençant par aa )

enter image description here

Réponses à vos questions:

"Quel est l'inventaire total pour Fruit?"

=COUNTIFS(Table1[long code],VLOOKUP(I3,Table1,5,FALSE)&"*",Table1[has child],FALSE)
selon le modèle, tous les éléments suivent la même séquence de départ. Je ne présente ici que des articles et non des catégories (vous vendez deux types de fruits apples et grapes, vous n'avez pas de produit appelé fruit vendre). Si vous souhaitez également compter les catégories, excluez simplement la deuxième partie de la formule.

"Combien de types d'aliments puis-je vendre?"

=SUMIF(Table1[long code],VLOOKUP(I10,Table1,5,FALSE)&"*",Table1[inventory])
Assez similaire avec SUMIF

Attention

Cette solution a deux limitations:

  • nombre de caractères: il commence à partir de a, qui a un code de 97, et dernier caractère supporté dans CHAR la fonction est 255, donc avoir plus de 158 catégories différentes dans n'importe quel niveau vous donnera une erreur (vous pouvez la développer un peu en utilisant un caractère avec un code plus petit pour la première)
  • à mesure que votre base de données augmente, les performances (calculs complexes) vont probablement diminuer, vous souhaiterez peut-être définir la méthode de calcul sur "Automatique sauf pour les tableaux de données" et la calculer manuellement au moment opportun.
Máté Juhász
la source
0

Je pense que Máté a une bonne réponse. La façon dont je le ferais serait avec des listes:

enter image description here

(Toutes les formules de tableau, donc Ctrl + Shft + Entrer )

Donc, les formules (faites glisser)

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))

Maintenant, selon la façon dont vous décidez de les trier, vous pouvez certainement créer une hiérarchie ou utiliser un tableau croisé dynamique.

Je donnerais probablement des noms de colonnes A et B afin que vous puissiez travailler avec des plages nommées.

Raystafarian
la source