У вас здесь несколько разных проблем, и это зависит от структуры данных. К счастью, вы этого не сделали, поэтому я решил!
Что мы собираемся предположить, у вас есть такой набор данных. Вы также можете приобрести две покупки BigWidget в две строки (и аналогичные для других продуктов), что не повлияет на это.
data customers;
length product $20;
input name $ product $ store $ count;
datalines;
Joe SmallWidget Store1 1
Joe LargeWidget Store1 2
Joe Mousepad Store1 1
Joe TeaPitcher Store2 1
Jack SmallWidget Store2 1
Jack Mousepad Store1 1
Jane LargeWidget Store2 1
Jane Mousepad Store1 1
Jill LargeWidget Store3 1
;;;;
run;
Тогда нам нужно сделать еще одну настройку: определить, как вы собираетесь группировать вещи. Многоканальные форматы позволяют вам запрашивать одно значение для нескольких кодов (т. Е. Большие виджеты и все виджеты). Это один из примеров, здесь вы можете сделать много разных вещей; вы также можете сделать это из набора данных (посмотрите на вариант CNTLIN
в формате proc или задайте другой вопрос).
proc format;
value $prodgroup (multilabel default=20)
SmallWidget = "Small Widgets"
SmallWidget = Widgets
LargeWidget = "Large Widgets"
LargeWidget = Widgets
Mousepad = Mousepads
Mousepad = "Misc Products"
TeaPitcher = "Tea Pitchers"
TeaPitcher = "Misc Products"
;
value $storeRegions (multilabel)
Store1=Store1
Store1=West
Store2=Store2
Store2=East
Store3=Store3
Store3=East
;
quit;
Затем мы сталкиваемся с большой проблемой: SAS сосет при расчете «разных» вещей. На самом деле этого не было сделано. Я не знаю почему; табулировать действительно нужно, но это не так. Тем не менее, это действительно хорошая задача поместить вещи в ведра, и это действительно тяжелая часть здесь; фактический отдельный счетный бит может быть выполнен во втором проходе (который, независимо от вашего начального размера данных, будет очень быстрым, если у вас будет гораздо меньше видов продуктов, чем у вас есть данные).
proc tabulate data=customers out=custdata;
class product store /mlf preloadfmt order=data;
class name;
format product $prodgroup20.;
format store $storeRegions6.;
tables (all store product store*product),name*n;
run;
proc tabulate data=custdata;
class product store/missing;
tables (product*store), n;
run;
MLF PRELOADFMT ORDER=DATA
делает MultiLabel битную работу должным образом и делает его выйти в полезном порядке (на мой взгляд). Вы можете добавить NOTSORTED
в оператор значения в PROC FORMAT
, чтобы получить еще больший контроль, хотя второй PROC TABULATE
просто испортит порядок, поэтому я бы не стал беспокоиться.
В этом случае мы сначала создаем таблицу, которая является клиентом, затем эта таблица выводится в набор данных; этот набор данных теперь, как гарантируется, будет содержать одну строку на каждого клиента за [независимо от группировки], если группировки отражаются в обоих procs (за вычетом класса NAME!).
Единственный недостаток этого процесса состоит в том, что он не создает линии для тех продуктов, для которых 0 необходимо сделать, чтобы вам не нужно было иметь второе табулирование, а вместо этого делать это в SQL или на шаге данных. Например:
proc tabulate data=customers out=custdata2;
class product store /mlf preloadfmt order=data;
class name;
format product $prodgroup20.;
format store $storeRegions6.;
tables (all store product store*product),name*n/printmiss;
run;
proc sql;
select product, store, sum(case when n>0 then 1 else 0 end) as count
from custdata2
group by product,store;
quit;
Обратите внимание на одно изменение в строке таблицы: printmiss
, который инструктирует Tabulate, чтобы сделать одну линию для каждой возможной комбинации независимо от того, что. Затем SQL
выполняет остальную часть работы. Конечно, этот SQL также мог бы повторить второй оператор Tabulate раньше, если вы предпочитаете SQL.
Надеюсь, что Джо ответит на этот вопрос – mjsqu
Этот вопрос будет полезен для некоторых образцов данных, мне сложно визуализировать. Не могли бы вы добавить свои исходные данные и как вы ожидаете, что это будет выглядеть, когда вы закончите. Для дополнительного кредита добавьте все запрошенные вами запросы. – mjsqu
Спасибо за три ответа ниже (и комментарии от mjsqu). Я намеренно ушел из данных и попытался просто описать ситуацию относительно простым способом. Вам все еще удалось выйти за пределы и обеспечить и очень подробные решения. Все предлагаемые идеи будут полезны в какой-то момент. – Oliver