4

Я пытаюсь найти способ агрегирования данных в иерархическом наборе данных, предпочтительно в сводной таблице, но другие методы также могут быть в порядке. Рассмотрим набор данных (значительно упрощенный для примера), который выглядит как приведенный ниже. Из этих данных я пытаюсь построить набор функций, которые будут отвечать на такие вопросы, как:

«Сколько всего инвентаря у меня есть для фруктов?"

«Сколько разных видов еды я продаю?"

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

Каждый элемент имеет (среди множества другой информации) категорию, которую мы можем считать "родителем". Но также обратите внимание, что в наборе данных все "родители" также имеют свои собственные родительские категории. В этом наборе данных одной выборочной "ветвью" иерархии будет « Пища-> Мясо-> Курица».

Ответить на вопрос типа "Сколько разных видов фруктов я продаю" несложно, потому что это категория первого уровня. Я могу просто использовать функцию 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

Легко - в первом ряду вы просто видите, сколько раз "Яблоки" появляются как чья-то категория. (Так как это ноль, я знаю, что Яблоки не являются родителями ... это должно помочь, но я не уверен, как ...) Теперь пятая строка, "Fruit", появляется как Чья-то Категория два раза - поскольку число НЕ равно нулю, я знаю, что это Категория, а не просто Предмет. Все хорошо для первого уровня математики, но ...

Это приводит меня к той части, которую я не смог решить ... Как я могу определить, сколько ВСЕХ видов "Еды" у меня есть? И учитывая, что мои фактические данные имеют гораздо больше уровней иерархии, мне нужно пройтись вверх и вниз по дереву, чтобы выяснить, сколько всего детей в каждом. Функция COUNTIF первого уровня говорит мне, что есть три подкатегории Food (Fruit, Veg, & Meat) - но я действительно хочу, чтобы как-то рекурсивно определить, что Fruit, Veg и Meat также могут быть Категории, и сумма до соответствующих номеров для этих детей. С точки зрения Excel, я действительно хочу иметь возможность построить еще один столбец, который рекурсивно / итеративно подсчитывает ИТОГО количество предметов во всем этом поддереве ... в этом случае есть семь уникальных предметов, которые относятся к еде: 3 мяса, 2 овоща и 2 фрукта.

Некоторые осложняющие факторы:

  • В данных нет явного идентификатора, который бы указывал нам, является ли этот конкретный элемент также категорией или это элемент нижнего уровня.

  • Каждый элемент знает только, что это за категория / родитель - нет явных данных, чтобы определить, есть ли у него дети или нет. Сказано иначе: все элементы принадлежат категории, но только некоторые элементы также являются категориями.

  • В реальных данных родительские отношения могут иметь глубину до 10 уровней, НО нет никаких гарантий, что глубина каждой ветви в иерархии последовательна: некоторые элементы могут иметь глубину 3 уровня, а следующая - 8.

  • Корневой или конечный родитель не имеет категории, но это единовременный случай, который я могу легко обработать вручную.

  • Я полностью осознаю, что это было бы тривиальным упражнением на любом "реальном" языке программирования (Perl, Python и т.д.)... но в конечном итоге я должен передать это кому-то, у кого нет опыта программирования, поэтому я изо всех сил стараюсь вписать это в "стандартную" книгу Excel.

2 ответа2

2

Сначала я полностью согласен с @Raystafarian, Excel не подходит для этого.

Однако, если вы действительно хотите сделать это здесь, вот решение с несколькими вспомогательными столбцами:

  • уровень: уровень фактического элемента в иерархии (корневые элементы имеют уровень 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]]
  • has child: логическое значение, указывающее, есть ли у элемента child
    =COUNTIF([Category],[@Item])>0

В этой модели категория содержит все элементы и подкатегории, код которых начинается с той же последовательности, что и родительский код (например, если код fruit - aa , то все (grand ...) его дочерние элементы имеют код, начинающийся с aa)

Ответы на ваши вопросы:

«Сколько всего инвентаря у меня есть для фруктов?"

=COUNTIFS(Table1[long code],VLOOKUP(I3,Table1,5,FALSE)&"*",Table1[has child],FALSE)
только в зависимости от модели, все элементы с одинаковой стартовой последовательностью. Я coun't здесь только предметы не категории (вы продаете два типа фруктов apples и grapes вы не имеете продукт под названием fruit на продажу). Если вы хотите посчитать также категории, то просто исключите вторую часть формулы.

«Сколько разных видов еды я продаю?"

=SUMIF(Table1[long code],VLOOKUP(I10,Table1,5,FALSE)&"*",Table1[inventory])
Очень похоже на SUMIF

Предупреждение

Это решение имеет два ограничения:

  • количество символов: в настоящее время он начинается с символа a , который имеет код 97, а последний поддерживаемый символ в функции CHAR равен 255, поэтому наличие более 158 различных категорий на любом уровне приведет к ошибке (вы можете немного расширить ее, используя символ с меньшим кодом для первого)
  • поскольку ваша база данных увеличивается, вероятно, это приведет к снижению производительности (сложные вычисления), вы можете захотеть установить метод расчета «автоматический, за исключением таблиц данных» и вычислять его вручную только тогда, когда вам это нужно.
0

Я думаю, что у Мате хороший ответ. То, как я это сделал бы, было бы со списками:

(Все формулы массива, поэтому 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, чтобы вы могли работать с именованными диапазонами.

Всё ещё ищете ответ? Посмотрите другие вопросы с метками .