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.
Save $250 on SAS Innovate and get a free advance copy of the new SAS For Dummies book! Use the code "SASforDummies" to register. Don't miss out, May 6-9, in Orlando, Florida.
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.