Столбцы суммы символов, пока граф не достиг - PullRequest
0 голосов
/ 27 августа 2018

У меня есть таблица, которая выглядит примерно так (с большим количеством записей и большим количеством заметок):

+------+---------------+------+---------------+------+---------------+------+
|id    |note_1         |len_1 |note_2         |len_2 |note_3         |len_3 |  
+------+---------------+------+---------------+------+---------------+------+
|10001 |"abcde"        |5     |"abc"          |3     |"abcdefg"      |7     |  
|10002 |"defghijk"     |8     |"ghuio"        |5     |"yuio"         |4     | 
|10003 |"abc"          |3     |"defg"         |4     |"qw"           |2     | 
+------+---------------+------+---------------+------+---------------+------+

и я хотел бы создать цикл do в шаге SAS data, который объединяет все ноты до достижения определенной длины (в данном примере, длины 10). Вот идеальный столбец, который будет создан для этого примера с максимальным значением 10:

+------+--------------+
|id    |concat_notes  |
+------+--------------+
|10001 |"abcdeabcab"  |
|10002 |"defghijkgh"  |
|10003 |"abcdefgqw"   |
+------+--------------+

Вот код, который я пытаюсь создать:

data length;
set notes;
concats = "";
do i=1 to 3;
    if (vvaluex(cats("len_",i)) > 10) then concat_notes= concats;
    else concats = cats(concats,vvaluex(cats("note_",i)));
end;
run;

Примечание. На самом деле все заметки очень длинные, и моя максимальная длина равна 32767. Я не могу объединить их все и использовать substrn, чтобы взять первые 32 767 из-за недостатка места.

Ответы [ 2 ]

0 голосов
/ 27 августа 2018

Указанная фактическая максимальная длина составляет 32 767, что также является максимальной длиной символьных переменных SAS. Таким образом, вам может потребоваться легкая конкатенация нужных переменных и позволить нормальное усечение, если результат превысит 32 тыс. Символов.

Надежный код будет использовать оператор length, чтобы указать, сколько места будет выделено для переменной, в которой хранится результат.

set notes;
length notes_catted $32767;
notes_catted = cats (of note_:);

негрубый

set notes;
notes_catted = cats (of note_:);  * variable will be given implicit default length $200;

Если длина не указана, компилятор шага DATA решит создать вместо нее переменную длины $ 200. Из файла справки:

Длина возвращаемой переменной

Если на шаге DATA функция CATS возвращает значение переменной, которой ранее не была назначена длина, то этой переменной присваивается длина 200 байтов. Дополнительно (мой курсив) , если оператор конкатенации (||) возвращает значение переменной, которой ранее не была назначена длина, то этой переменной присваивается длина, равная сумме длин значения, которые объединяются.

0 голосов
/ 27 августа 2018

Похоже, вы можете просто проверить длину напрямую:

%let max_length=10;
data have;
input id note_1 $ len_1 note_2 $ len_2 note_3 $ len_3;
datalines;
  10001    abcde           5        abc             3        abcdefg         7         
  10002    defghijk        8        ghuio           5        yuio            4        
  10003    abc             3        defg            4        qw              2        
;;;;
run;
data want;
  set have;
  array notes note_:;
  length cat_note $10;
  do _i = 1 to dim(notes);
    if length(cat_note) + length(notes[_i]) le &max_length. then 
        cat_note = cats(cat_note,notes[_i]);
    else if length(cat_note) lt &max_length. then 
        cat_note = cats(cat_note, substr(notes[_i],1,(&max_length.-length(cat_note))));  *added to get last bit;
  end;
  keep id cat_note;
run;

Вы также можете просто напрямую добавить длину, если есть причина, по которой вы не хотите использовать функцию length для проверки длины, но это кажется хорошим с точки зрения производительности ... не проходите через это vvaluex но это не имеет смысла. Просто создайте переменную суммирования и каждый раз, когда вы объединяете что-то, добавляйте к нему.

Помните, что length () для символьных переменных возвращает длину до последнего непробельного символа, так что это точно отражает то, что вы ищете.

Отредактировано для добавления остатка, чтобы точно получить 10.

...