BookmarkSubscribeRSS Feed
Jeff_DOC
Pyrite | Level 9

Hello.

 

I have a problem I'm hoping someone can help me with. I have a large list of the type at the bottom. I need to parse out the numbers from the string in var2 and then compare the result to a range. For instance, the range may be from 13 to 35 and I need to find which desks fit into that range. So if I can parse out the numbers and they determine if they are within a particular range that'd be perfect. I've attempted to use:

 

data test_1;

set have;

     if compress(var2,'', 'A') >= &range_1. and compress(var2,'', 'A') <= &range_2.  then test = 'YEAH';

run;

 

 to parse out the numbers and they come out alpha. I've also tried:

 

data test_1;

  set have;

    if input(compress(var2,'', 'A'), 8.) >= &range_1. and input(compress(var2,'', 'A'), 8.) <= &range_2. then test = 'YEAH';

run;

 

When I use either method above in order to convert the result to a number so I can use GE and LE to compare to the criteria range I get an error: 

     ERROR 388-185: Expecting an arithmetic operator.

 

My macro variables are defined as:

     %let range_1 = 13;
     %let range_2 = 24;

so they appear to be numeric so I'm not sure where my error might be?

 

Thanks to anyone who can take the time to help me out.

 

var1 var2 WANT
ROOMA DESK01A 1
ROOMA DESK01B 1
ROOMA DESK05B 5
ROOMA DESK06A 6
ROOMB DESK09A 9
ROOMB DESK09B 9
ROOMC DESK01B 1
ROOMC DESK05A 5
ROOMD DESK10B 10
ROOME DESK15A 15
ROOME DESK15B 15
ROOME DESK16 16
5 REPLIES 5
sbxkoenk
SAS Super FREQ
data _NULL_;
 a='DESK05B';
 /* Compressing Space Characters by Using a Modifier   */
 b=compress(a, '', 's');
 /* Keeping Characters in the List by Using a Modifier */
 c=compress(b, '0123456789', 'k');
 put c=;
 d=input(c,2.);
 put d=;
 if 3 < d < 7 then test = 'YEAH';
 put test=;
run;

Ciao,

Koen

PaigeMiller
Diamond | Level 26
compress(var2,'', 'A')

 

The COMPRESS function produces a character string, in this case a character string of the letters in VAR2. For the first row of your data set you get the character string '01'. It is not a number, even if it looks like a number to you, so SAS does not know how to evaluate if the character string '01' is greater than &range_1, which is a number. SAS cannot compare characters strings to numbers. So to fix this, you want to convert the character string from var2 into an actual number. You do this by

 

input(compress(var2,'', 'A'),3.)

 

which turns the character string into the actual number 1. Then it can be compared to the number in &range_1. This will handle numbers up to 3 digits wide (i.e <= 999).

 

My macro variables are defined as:

%let range_1 = 13;
%let range_2 = 24;

so they appear to be numeric so I'm not sure where my error might be?

 

The values of macro variables are always text, no matter that they look like numbers. The only way they become numbers is if you use them in a way that SAS recognizes them as numbers. In this case, when SAS evaluates the code, it replaces &range_1 with 13, and so then the code actually becomes 

 

compress(var2,'', 'A') > 13

 

and then SAS recognizes 13 as a number from the context. Do you know why in the above line that 13 is treated as a number and not a character string?

 

@Jeff_DOC you're not new here. Please be a good citizen of the community and help us just as we are trying to help you. When you get errors in the log, then SHOW US THE LOG. We need to see the entire log for the DATA step (or PROC) that has the error from now on, without having ask.

--
Paige Miller
ballardw
Super User

It is a good idea to paste your code by copy from your editor and paste into a text box opened on the forum using the </> icon above the message window. The forum software will reformat text when pasted into the main message window and may hide the actual problem because of the conversion. 

 

From ancient behaviors with some keyboards I don't trust >= and =< and use the SAS GE and LE comparisons in code. Sometimes a >= or <= may just happen to be a single character in an extended character set that SAS won't use for comparisons.

 

It is also a good idea to provide data in the form of a working data step as when I create data set such as with this data step:

data have;
  input var1 $ var2 $;
datalines;
ROOMA 	DESK01A 	
ROOMA 	DESK01B 	
ROOMA 	DESK05B 	
ROOMA 	DESK06A 	
ROOMB 	DESK09A 	
ROOMB 	DESK09B 	
ROOMC 	DESK01B 	
ROOMC 	DESK05A 	
ROOMD 	DESK10B 	
ROOME 	DESK15A 	
ROOME 	DESK15B 	
ROOME 	DESK16 	
;

And get this log for YOUR code:

101    %let range_1 = 13;
102    %let range_2 = 24;
103  data test;
104     set have;
105     if input(compress(var2,'', 'A'), 8.) >= &range_1. and
105! input(compress(var2,'', 'A'), 8.) <= &range_2. then test = 'YEAH';
106  run;

NOTE: There were 12 observations read from the data set WORK.HAVE.
NOTE: The data set WORK.TEST has 12 observations and 3 variables.
NOTE: DATA statement used (Total process time):
      real time           0.00 seconds
      cpu time            0.00 seconds

which has no error. So one suspects something in your data may be involved.

Resulting data set:

var1 var2 test
ROOMA DESK01A  
ROOMA DESK01B  
ROOMA DESK05B  
ROOMA DESK06A  
ROOMB DESK09A  
ROOMB DESK09B  
ROOMC DESK01B  
ROOMC DESK05A  
ROOMD DESK10B  
ROOME DESK15A YEAH
ROOME DESK15B YEAH
ROOME DESK16 YEAH

 

 

The variables Var1 and Var2 are length 8. If your variables  white space values like leading spaces, tabs or NULL characters (ASCII 255) then we can't see those and may be reformatted by the forum software to blanks.  

 

I would try using :   compress(var2,'', 'dk') to keep only digits. This would protect against non-displayed characters like Null.

With those thoughts in mind, when I create a data set with this code:

data have;
  input var1 $ var2 $;
datalines;
ROOMA 	DESK01A 	
ROOMA 	DESK01B 	
ROOMA 	DESK05B 	
ROOMA 	DESK06A 	
ROOMB 	DESK09A 	
ROOMB 	DESK09B 	
ROOMC 	DESK01B 	
ROOMC 	DESK05A 	
ROOMD 	DESK10B 	
ROOME 	DESK15A 	
ROOME 	DESK15B 	
ROOME 	DESK16 	
;

 

 

Also any error message should be copied from the log with the code of the procedure or data step that generates the error along with the error and all other notes or warnings for that step. Copy the text from the log, open a text box using the </> and paste. Many of those errors will have diagnostics that indicate where the error is found.

 

 

As an aside, I strongly recommend using numeric results in stead of 'Yes' or similar for comparisons especially if the result is binary Yes/No, True/False, Present/Not present or similar.

You could use

Test = value1 LE TestValue LE value; 

Test would have value 1 when true and 0 when false.  It is often much easier to get reportable values from the numeric values a Sum of Test would have the count of true values, mean would be the percentage true values as as decimal. Questions like all true, all false, more true than false are also often easier to determine using sum of the variable compared to count of values, N statistic, in proc summary, means, report or tabulate than dealing with character values.

 

Patrick
Opal | Level 21

Something like below should do.

data have;
  input var1 $ var2 $;
datalines;
ROOMA 	DESK01A 	
ROOMA 	DESK01B 	
ROOMA 	DESK05B 	
ROOMA 	DESK06A 	
ROOMB 	DESK09A 	
ROOMB 	DESK09B 	
ROOMC 	DESK01B 	
ROOMC 	DESK05A 	
ROOMD 	DESK10B 	
ROOME 	DESK15A 	
ROOME 	DESK15B 	
ROOME 	DESK16 	
ROOME 	DESK 	
;

proc format;
	value range
	.   			= 'missing'
	low - 5 	= 'Range 1'
	5 -  10 	= 'Range 2'
	10 - high	= 'Range 3'
	;
run;

data want;
	set have;
	nums=input(scan(var2,1,,'kd'),best32.);
run;

proc sql;
	select var1, var2, nums as nums1 format=best32., nums as nums2 format=range.
	from want
	;
quit;

Patrick_0-1764888160946.png

 



Tom
Super User Tom
Super User

Your first program does what it asked it to do.

data have;
  input var1 $ var2 $ WANT ;
cards;
ROOMA  DESK01A 1
ROOMA  DESK01B 1
ROOMA  DESK05B 5
ROOMA  DESK06A 6
ROOMB  DESK09A 9
ROOMB  DESK09B 9
ROOMC  DESK01B 1
ROOMC  DESK05A 5
ROOMD  DESK10B 10
ROOME  DESK15A 15
ROOME  DESK15B 15
ROOME  DESK16  16
;

%let range_1 = 13;
%let range_2 = 24;
data test_1;
  set have;
  if compress(var2,'', 'A') >= &range_1. 
  and compress(var2,'', 'A') <= &range_2.  
  then test = 'YEAH';
run;
proc print;
run;

 Results

Obs var1 var2 WANT test
1 ROOMA DESK01A 1  
2 ROOMA DESK01B 1  
3 ROOMA DESK05B 5  
4 ROOMA DESK06A 6  
5 ROOMB DESK09A 9  
6 ROOMB DESK09B 9  
7 ROOMC DESK01B 1  
8 ROOMC DESK05A 5  
9 ROOMD DESK10B 10  
10 ROOME DESK15A 15 YEAH
11 ROOME DESK15B 15 YEAH
12 ROOME DESK16 16 YEAH

 

But why does it work?  Because SAS helpfully automatically converted the strings like '1' and '15' that your COMPRESS() function call generated into numbers:

 90         data test_1;
 91           set have;
 92           if compress(var2,'', 'A') >= &range_1.
 93           and compress(var2,'', 'A') <= &range_2.
 94           then test = 'YEAH';
 95         run;
 
 NOTE: Character values have been converted to numeric values at the places given by: (Line):(Column).
       92:6   93:7   

If you want to convert the value to numbers yourself then use the INPUT() function.

data test_2;
  set have;
  test2 = input(compress(var2,' ','A'),32.);
  check= (test2 = want);
run;

Result

Obs var1 var2 WANT test2 check
1 ROOMA DESK01A 1 1 1
2 ROOMA DESK01B 1 1 1
3 ROOMA DESK05B 5 5 1
4 ROOMA DESK06A 6 6 1
5 ROOMB DESK09A 9 9 1
6 ROOMB DESK09B 9 9 1
7 ROOMC DESK01B 1 1 1
8 ROOMC DESK05A 5 5 1
9 ROOMD DESK10B 10 10 1
10 ROOME DESK15A 15 15 1
11 ROOME DESK15B 15 15 1
12 ROOME DESK16 16 16 1

 

Two things to note.

1) I explicitly asked COMPRESS() to remove spaces as well has letters.  You might also instead try tell it to only keep digits.

2) I used the 32. informat to read the generated string.  The INPUT() function does not care if the width of the informat being used is larger than the length of the string being read.  And since 32 is the maximum width that the numeric informat supports it is best to use that when you don't know how long the string being read might be.

 

sas-innovate-2026-white.png



April 27 – 30 | Gaylord Texan | Grapevine, Texas

Registration is open

Walk in ready to learn. Walk out ready to deliver. This is the data and AI conference you can't afford to miss.
Register now and lock in 2025 pricing—just $495!

Register now

How to Concatenate Values

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.

SAS Training: Just a Click Away

 Ready to level-up your skills? Choose your own adventure.

Browse our catalog!

Discussion stats
  • 5 replies
  • 108 views
  • 0 likes
  • 6 in conversation