I am adding a prefix to each word in a macro variable. However, when using my current method, the first word does not receive the prefix. Looking at my code, there is good reason for this as there is no space in front of the word.
The code i use is:
%LET independent_vars = FF_1 FF_4 FF_7 FF_10;
%LET log_independent_vars = %SYSFUNC(TRANWRD(&independent_vars.,%str( ),%str( ln_)));
%PUT &log_independent_vars.;
Current output is:
FF_1 ln_FF_4 ln_FF_7 ln_FF_10
Expected output is:
ln_FF_1 ln_FF_4 ln_FF_7 ln_FF_10
I've tried using prxchange but I don't understand it
Only the first space is stripped
You can circumvent this problem by adding one 'ln_' in front of your formula
%LET independent_vars = FF_1 FF_4 FF_7 FF_10;
%LET log_independent_vars = ln_%SYSFUNC(TRANWRD(&independent_vars.,%str( ),%str( ln_)));
%PUT &log_independent_vars.;
ln_FF_1 ln_FF_4 ln_FF_7 ln_FF_10
Related
I have had to look up hundreds (if not thousands) of free-text answers on google, making notes in Excel along the way and inserting SAS-code around the answers as a last step.
The output looks like this:
This output contains an unnecessary number of blank spaces, which seems to confuse SAS's search to the point where the observations can't be properly located.
It works if I manually erase superflous spaces, but that will probably take hours. Is there an automated fix for this, either in SAS or in excel?
I tried using the STRIP-function, to no avail:
else if R_res_ort_txt=strip(" arild ") and R_kom_lan=strip(" skåne ") then R_kommun=strip(" Höganäs " );
If you want to generate a string like:
if R_res_ort_txt="arild" and R_kom_lan="skåne" then R_kommun="Höganäs";
from three variables, let's call them A B C, then just use code like:
string=catx(' ','if R_res_ort_txt=',quote(trim(A))
,'and R_kom_lan=',quote(trim(B))
,'then R_kommun=',quote(trim(C)),';') ;
Or if you are just writing that string to a file just use this PUT statement syntax.
put 'if R_res_ort_txt=' A :$quote. 'and R_kom_lan=' B :$quote.
'then R_kommun=' C :$quote. ';' ;
A saner solution would be to continue using the free-text answers as data and perform your matching criteria for transformations with a left join.
proc import out=answers datafile='my-free-text-answers.xlsx';
data have;
attrib R_res_ort_txt R_kom_lan length=$100;
input R_res_ort_txt ...;
datalines4;
... whatever all those transforms will be performed on...
;;;;
proc sql;
create table want as
select
have.* ,
answers.R_kommun_answer as R_kommun
from
have
left join
answers
on
have.R_res_ort_txt = answers.res_ort_answer
& have.R_kom_lan = abswers.kom_lan_answer
;
I solved this by adding quotes in excel using the flash fill function:
https://www.youtube.com/watch?v=nE65QeDoepc
All:
when performing IN operator to match words in a macro string, the quotes are required. But, the results are frustrated, would someone remind me what I have missed.
This macro string is created from proc sql as below
'''
proc sql noprint;
select memname into :domains separated by ' '
from sashelp.vtable
where libname='SDTM';
quit;
'''
Next, I quoted the string using this statement
'''
%let domains_quoted = %nrbquote(')%qsysfunc(prxchange(s/\s+/%nrbquote(',')/oi,-1,&domains))%nrbquote(');
'''
In log, it displayed no issues
SYMBOLGEN: Macro variable DOMAINS_QUOTED resolves to 'AE','CM','DM','DS','EG','EX',...
Then, I wish I can filter the output datasets.
'''
data want;
set have;
if dname in (&domains_quoted);
run;
'''
I got the error message saying:
SYMBOLGEN: Some characters in the above value which were subject to macro quoting have been unquoted for printing.
ERROR 22-322: Syntax error, expecting one of the following: a quoted string, a numeric constant, a datetime constant,
a missing value, iterator, (.
Would some one remind me what I have missed in these steps? Great appreciated.
Use the QUOTE() function to avoid the PRX step.
proc sql noprint;
select quote(memname) into :domains separated by ' '
from sashelp.vtable
where libname='SDTM';
quit;
data want;
set have;
if dname in (&domains_quoted);
run;
I need help modifying this code from SAS (http://support.sas.com/kb/33/078.html) to be:
Not case sensitive (therefore not overlooking SMITH versus Smith versus smith, I tried "upcase" but it won't work)
Include a counter (so that I can control for either knowing the first time a value appears and if needed, how many times the value appears)
Allow for a partial search (this code only allows for exact match to be searched which means I am missing many possible variables that the value could be defined under)
Thanks! :)
From your comment:
data _null_;
set &librf..&&ds&i;
%do j=1 %to &numvars;
if INDEX(upcase(&&var&j),"&string") >0 then
/*modified this part to satisfy the first and third things that I wanted*/
put "String &string found in dataset &librf..&&ds&i for variable &&var&j"
;
%end;
run;
So just add code to increment the counter. Do you want to count observations or occurrences? That is if the same observation has multiple hits does it count as one or multiple?
Counting each hit is easier:
data _null_;
set &librf..&&ds&i;
%do j=1 %to &numvars;
if INDEX(upcase(&&var&j),"&string") >0 then do;
_count+1;
put "String &string found in dataset &librf..&&ds&i for variable &&var&j" _count=;
end;
%end;
run;
Here is how you might count each observation.
data _null_;
set &librf..&&ds&i;
%do j=1 %to &numvars;
if INDEX(upcase(&&var&j),"&string") >0 then do;
_hit=1;
put "String &string found in dataset &librf..&&ds&i for variable &&var&j";
end;
%end;
if _hit then do;
_count+1;
put "Number of observations so far=" _count ;
end;
run;
Assuming you are running the code in the sample. I would change the comparison expression.
I would make it a macro parameter. You can use FIND/W/C, regular expression, etc.
exp=%str(find(&&var&j,'-target-','IT')),
%unquote(&exp) to replace underlined in red.
when using %STR(amy.goodman#yaho.com;bill.goodman#yaho.com;jack.goodman#yaho.com);
This gives me the result: amy.goodman#yaho.com;bill.goodman#yaho.com;jack.goodman#yaho.com
which is what I want. and this is a macro variable called &email. I need this semicolon in between any two emails but no semicolon after the last email
But for someone who has an single quote in her email address like O'Connor,
%str will automatically match the single quote
using %STR(amy.goodman#yaho.com;bill.goodman#yaho.com;lily.O'Connor#yaho.com) will cause error.
How can I get the result amy.goodman#yaho.com;bill.goodman#yaho.com;lily.O'Connor#yaho.com
by using %str or any other macro quote function like %bquote or anything else to keep that single quote unmatched?
THE EMAIL LIST IS imported from excel list and I already put% before the single quote in the excel file: lily.O%'Connor#yaho.com
and HOW can I get the the macro variable &email. value inside the %str(), namely:
amy.goodman#yaho.com;bill.goodman#yaho.com;lily.O%'Connor#yaho.com
then I can put macro variable into %str()?
If you have the value already in a macro variable, say from a data step via CALL SYMPUTX() function call or from PROC SQL via INTO clause, then you can use %SUPERQ() macro function to macro quote the value.
data _null_;
call symputx('unquoted',"O'Connor#domain.com");
run;
%put Email list = %superq(unquoted);
If the value is already in a macro variable the the %BQUOTE() function would also work.
%put Email list = %bquote(&unquoted);
You could even use the RESOLVE() function to call %SUPERQ() to get the macro variable redefined with macro quoting immediately after creating it. So if you have a dataset MYTABLE with a variable EMAIL_LIST you could generate a series of separate macro variables (list1,list2, etc) from the data using code like this.
data _null_;
set mytable ;
length mvar rc $32 ;
mvar = cats('list',_n_);
call symputx(mvar,email_list);
rc = resolve(catx(' ','%let',mvar,'=%superq(',mvar,');'));
run;
The first example data step works since the string literal used double quotes on the outside and thus protected the unbalanced single quote. You could do the same thing in macro code by using the %QSYSFUNC() macro function to call the DEQUOTE() function. Note that you would have trouble if the value includes double quote characters. They would need to be converted to two adjacent double quotes.
%put Email list = %qsysfunc(dequote("O'Connor#domain.com"));
With %STR, you need to mark unmatched quotes with a % sign. So try:
%STR(amy.goodman#yaho.com;bill.goodman#yaho.com;lily.O%'Connor#yaho.com)
Does anyone know how i can correct the following?
CODE:
%macro variables(list);
data tire.Import2(drop=i count);
set tire.Import;
by Away_Team;
%let n=%sysfunc(countw(&list));
%DO k=1 %TO &n;
%let val = %scan (&list,&k);
array x(*) &val.lag1-&val.lag6;
&val.lag1=lag1(&val);
&val.lag2=lag2(&val)+lag1(&val);
&val.lag3=lag3(&val)+lag2(&val)+lag1(&val);
&val.lag4=lag4(&val)+lag3(&val)+lag2(&val)+lag1(&val);
&val.lag5=lag5(&val)+lag4(&val)+lag3(&val)+lag2(&val)+lag1(&val);
&val.lag6=lag6(&val)+lag5(&val)+lag4(&val)+lag3(&val)+lag2(&val)+lag1(&val);
%if %str(first.Away_Team) %then count=1;
%do i=count %to dim(x);
x(i)=.;
%end;
count + 1;
run;
%end;
%mend;
%variables(FTHG FTHGC);
ERROR: A character operand was found in the %EVAL function or %IF
condition where a numeric operand is required. The condition was:
%str(first.Away_Team) ERROR: The macro VARIABLES will stop executing.
I tried using %bquote and %str but no luck!
Your macro is confusing macro %IF statements vs data step IF statements, and %DO loops vs DO loops. The macro language (%IF %DO etc) is used to generate SAS code. It does not know about SAS datasets or the values of dataset variables. It's just a text processing language. The SAS data step language (IF DO etc) is used to read and process data.
When you write:
%if %str(first.Away_Team) %then count=1;
this is a macro %IF statement. The macro language does not know about dataset variables such as first.Away_Team. So the macro %if statement is testing whether the expression %str(first.Away_Team) is true or not. This is just a text string to the macro language; it does not know that first.Away_Team is a data step variable that has a value of 1 or 0. So it throws an error.
This should be just a regular IF statement:
if first.Away_Team then count=1
The data step IF statement can test the value of first.Away_Team.
Similar for your %DO loop at the end. You cannot: %do i=count %to dim(x); because the macro language %DO statement does not know that COUNT is a dataset variable with a value, or that dim(x) is the number of elements in an array named x. To the macro language, they are both text strings. You can do i=count to dim(x);
I would suggest you start by writing your data step with no macros or macro variables at all, and get that working like you want it, for FTHG and FTHGC. Then after you know what the working SAS code is, you can try write a macro that will generate that code.