Hello everyone,,
I have a dataset of IE in that a variable TEST having greater than 200 Characters in some of its observation. I want those observation split into different variables having Length of 200 char.
Change the value of devidingColumnLength variable on line 2 to 200, while running the code on your data.
options mprint;
%let devidingColumnLength=10; /*Change it to 200, 10 is taken for demonstration here*/
data IE;
input test:$2000.;
cards;
qwertyuopasdfghjkl02jiimddjj10jn
299302nhfmmmskskkkkkkkqieijncnc20099839kkjjj
sjjdjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjalllllllll1
kk
8
kkkkkkkkkkkkkkkkkkkkkkkkkkkk333333333333333330000000000000000000099
iii
;
run;
proc sql noprint;
select max(length(test)) into:maxLen from IE;
quit;
%put &=maxLen;
%macro runit;
data IE;
set IE;
%do i=1 %to %eval(&maxLen./&devidingColumnLength. + 1);
%if &i=1 %then %do;
init=1;
%end;
if length(test) ge init then do;
TEST&i.=substr(test,init,&devidingColumnLength.);
init=init+&devidingColumnLength.;
end;
else return;
%end;
drop init;
run;
%mend runit;
%runit;
Please let us know if it worked for you.
Hi,
do you mean something like this:
%let split=20;
data have;
var = "abcdefghihbuiuhfnjbvjzknoiewhfkbvzncldlwhflva"; output;
var = "abcdefghihbuiuhfnjbvjz"; output;
var = "abc"; output;
run;
data _null_;
if 0 then set have;
call symputx("varLen", vlength(var));
stop;
run;
%let numOfSplits=%sysevalf(&varLen./&split., CEIL);
%put &=split. &=varLen. &=numOfSplits.;
data want;
set have;
array v[&numOfSplits.] $ &split. ;
j=0; drop i j;
do i = 1 to min(&varLen.,lengthn(var)) by &split.;
j+1;
v[j] = substr(var, i);
end;
run;
All the best
Bart
@yabwon: Bart, methinks it's more economical output-wise to base the splitting on the max LENGTH of the input VAR than on VLENGTH to avoid a bunch of empty trailing output VV's in case the system length >> actual max length. I.e., something like:
data have ;
length var $ 100 ;
do var = "abcdefghihbuiuhfnjbvjzknoiewhfkbvzncldlwhflva"
, "abcdefghihbuiuhfnjbvjz"
, "abc" ;
output ;
end ;
run ;
%let split = 20 ;
proc sql noprint ;
select max (ceil (divide (length (var), &split))) into :ns from have ;
quit ;
data want ;
set have ;
array vv [&ns] $ &split ;
do _n_ = 1 to &ns ;
vv[_n_] = substrn (var, (_n_ - 1) * &split + 1) ;
end ;
run ;
Kind regards
Paul D.
Pavle, that's why I've made it:
do i = 1 to min(&varLen.,lengthn(var)) by &split.;
so we have only 1 data read 🙂
All the best
Bart
@hashman ,
Pavle, I didn't get your point after first reading. Now I understood. You are 100% right, to wide array may be created without that additional pre-check.
All the best
Bart
Barteku, yup, that was my understanding. Fewer passes through the input is a noble goal. And I did realize that I was making an extra pass, just my angle was a bit different here, so I decided it was worth the sacrifice ;).
Kind regards
Paul D.
It's finally time to hack! Remember to visit the SAS Hacker's Hub regularly for news and updates.
Learn how use the CAT functions in SAS to join values from multiple variables into a single value.
Find more tutorials on the SAS Users YouTube channel.
Ready to level-up your skills? Choose your own adventure.