Сортировка почти отсортированного набора данных в SAS

У меня есть большой набор данных в SAS, который, как я знаю, почти отсортирован; я знаю, что первый и второй уровни отсортированы, но третий уровень-нет. Кроме того, первый и второй уровни содержат большое количество различных значений и поэтому еще меньше хочется снова первые два столбца, когда я знаю, что это уже в правильном порядке. Пример данных приведен ниже:

ID  Label    Frequency
1   Jon      20
1   John     5
2   Mathieu  2
2   Mathhew  7
2   Matt     5
3   Nat      1
3   Natalie  4

используя опцию "presorted" на Сортировке proc, похоже, только проверяет, являются ли данные сортируется по каждому ключу, иначе он делает полный вид данных. Есть ли способ сказать SAS, что первые два столбца уже отсортированы?

1 ответов


если вы ранее отсортировали набор данных по первым 2 переменным, то независимо от sortedby информация о наборе данных, SAS займет меньше времени процессора, чтобы отсортировать его *. Это естественное свойство большинства приличных алгоритмов сортировки - гораздо меньше работы для сортировки того, что уже почти Отсортировано.

* до тех пор, пока вы не используете на proc sort оператор, который заставляет его выполнять избыточную сортировку.

вот небольшой тест I РАН:

option fullstimer;
/*Make sure we have plenty of rows with the same 1 + 2 values, so that sorting by 1 + 2 doesn't imply that the dataset is already sorted by 1 + 2 + 3*/
data test;
    do _n_ = 1 to 10000000;
        var1 = round(rand('uniform'),0.0001);
        var2 = round(rand('uniform'),0.0001);
        var3 = round(rand('uniform'),0.0001);
        output;
    end;
run;

/*Sort by all 3 vars at once*/
proc sort data = test out = sort_all;
    by var1 var2 var3;
run;

/*Create a baseline dataset already sorted by 2/3 vars*/
/*N.B. proc sort adds sortedby information to the output dataset*/
proc sort data = test out = baseline;
    by var1 var2;
run;

/*Sort baseline by all 3 vars*/
proc sort data = baseline out = sort_3a;
    by var1 var2 var3;
run;

/*Remove sort information from baseline dataset (leaving the order of observations unchanged)*/
proc datasets lib = work nolist nodetails;
    modify baseline (sortedby = _NULL_);
    run;
quit;

/*Sort baseline dataset again*/
proc sort data = baseline out = sort_3b;
    by var1 var2 var3;
run;

соответствующие результаты, которые я получил, были следующими:

  • SAS потребовалось 8 секунд, чтобы отсортировать исходный полностью несортированный набор данных по всем 3 переменным.
  • SAS потребовалось 4 секунды для сортировки на 3/3, начиная с базового набора данных, уже отсортированного по 2/3 переменным.
  • SAS потребовалось 4 секунды для сортировки на 3/3, начиная с того же базового набора данных после удаления из него информации о сортировке.

соответствующая метрика из выхода журнала - это количество времени процессора пользователя.

конечно, если почти отсортированный набор данных очень большой и содержит много других переменных, вы можете избежать сортировки из-за накладных расходов на запись при его замене. Другой подход, который вы могли бы принять, - это создать составной индекс-это позволит вам делать вещи, связанные с групповой обработкой, например.

/*Alternative option - index the 2/3 sorted dataset on all 3 vars rather than sorting it*/
proc datasets lib = work nolist nodetails;
    /*Replace the sort information*/
    modify baseline(sortedby = var1 var2);
    run;
    /*Create composite index*/
    modify baseline;
    index create index1 = (var1 var2 var3);
    run;
quit;

создание индекса требует чтения всего набора данных, как это делает, но только часть работы, связанной с написанием его снова, и может быть быстрее, чем сортировка от 2/3 до 3/3 в некоторых ситуациях.