Hello!
I am attempting to create a variable in my data that is the sum of the characters in a string (comprised of 0s and 1s). The code below does sum the 1s in the string, but I'm not sure how to manipulate it to provide the information that I'm looking for. For those whose strings start with 1s and change to 0s, that is ok. For those whose strings start with 0, regardless of the 1s that may follow, those need to be set to 0. Lastly, for those whose strings have 0s in the middle of the 1s, I need to only sum the 1s before it hits the 0. I apologize if this seems confusing and have tried to provide an illustration below of the string and the sum that I would like to calculate. Any help would be most appreciated!
x_all sum that code below calculates sum that I want
1111111000000 6 6
0000001111111 7 0
1111000111111 10 4
data want (drop = i );
set have;
x_total=0;
do i=1 to length(x_all);
x_total+input(substr(x_all,i,1),1.);
end;
HI @silversta If I understand you correctly, it's a simple boolean expression.
data have;
input x_all :$20.;* sum that code below calculates sum that I want;
cards;
1111111000000 6 6
0000001111111 7 0
1111000111111
;
data want;
set have;
want=(verify(x_all,'1')>1)*(verify(x_all,'1')-1);
run;
Use a do while:
data want (drop = i );
set have;
x_total = 0;
i = 1;
do while (substr(x_all,i,1) = '1' and i le length(x_all));
x_total + 1;
i + 1;
end;
run;
HI @silversta If I understand you correctly, it's a simple boolean expression.
data have;
input x_all :$20.;* sum that code below calculates sum that I want;
cards;
1111111000000 6 6
0000001111111 7 0
1111000111111
;
data want;
set have;
want=(verify(x_all,'1')>1)*(verify(x_all,'1')-1);
run;
Yes indeed. Good catch. I'll have to be a more diligent like you are. Thank you!
Hi @biopharma I just showed my mother(a retired banker) how elegantly you made it more terse. However she thinks it's better to have boolean 1 capture in case of missings and value not padded with blank i.e if incoming data is equivalent to something like stripped(x_all) a missing value the risk of having -1 in the result is apparent, albeit I'd still vote opposing my mom's thoughts for the reason that occurence is less likely.
I can't generally win against her if there's even a remote chance, so it appears the following is what she means. lol
data have;
input x_all :$20.;* sum that code below calculates sum that I want;
cards;
1111111000000 6 6
0000001111111 7 0
1111000111111
.
;
data want;
set have;
want=(verify(strip(x_all),'1')-1);
want1=(verify(strip(x_all),'1')>1)*(verify(strip(x_all),'1')-1);
run;
Fun stuff:)
In general with VERIFY() you have to control for the case when the value being passed is completely filled with valid values. In that case the result returned will be zero, not the length of the string. So when you are using it to to find the last valid value, like in this case, you can just append some invalid character to the end of the string you pass it. As long are your input string is not exactly 32,767 bytes long it should do what you want.
want = verify(x_all || ' ','1')-1 ;
I agree. It's a very tricky function yet a very classy one.
Hello @novinosrin,
Thanks again for the code, it was most helpful! Is there a way to modify it to sum through a string of 1 or 2 0s in the middle. I was told that I would have to count the 0s in the middle of the string as if it were a 1, as long as there are no more than 2 of them in the middle.
For example:
11110000011 = 4
111001111 =9
111001111000 =9 (would ignore the 0s at the end but count the 0s in the middle as part of the sum)
Hi, try this:
data have;
input x_all :$20. expected ;
cards;
11110000011 4
111001111 9
111001111000 9
;
run;
data want;
set have;
want = lengthn(prxchange('s/^((1*)0{0,2}(1+))(.*)/$1/', -1, strip(x_all)));
run;
proc print data=want;
run;
Bart
Hi @silversta
Can you please explain a bit more clearly how you got this result
11110000011 = 4
111001111 =9
111001111000 =9
Would the above mean the following?
11101111 =8
based upon "Is there a way to modify it to sum through a string of 1 or 2 0s in the middle. I was told that I would have to count the 0s in the middle of the string as if it were a 1, as long as there are no more than 2 of them in the middle. "
Addendum-
@yabwon has answered your additional requirement even before I could begin
SAS Innovate 2025 is scheduled for May 6-9 in Orlando, FL. Sign up to be first to learn about the agenda and registration!
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.