Overlay SAS GMAP Choropleths - plot

Reformulation: I want to overlay the following two Graphs:
data mystates;
set maps.states;
myvar = state<30;
run;
pattern1 c=black v=m3n0;
pattern2 c=black v=m3n90;
%let except = (where=(state not in (72,2,15)));
proc gmap map=mystates &except. data=mystates &except.;
id state;
choro myvar;
run;
quit;
And
goptions reset=all;
%let no = 48;
proc gmap map=maps.counties (where =(state=&no.)) data=maps.counties (where =(state=&no.));
id county;
choro county;
run;
quit;
As the granularity is different I cannot simply use 2 choro statements in teh proc gmap: Note how the order of the two choro statements matters. One always overdraws the other.
data mytry;
set mystates &except. maps.county (where =(state=&no.));
run;
pattern1 c=black v=m3n0;
pattern2 c=black v=m3n90;
proc gmap map=mytry data=mytry all;
id state county;
choro myvar;
choro county;
run;
quit;
How can I display both the lines and the colors at the same time?

Related

R: export multiple workbook excel from a dataset by a variable

i have a statistical df organised by years, for example 5 and i'll would like to export my table in 5 different Excel Workbook, how can i do? First i used SAS and i did it with macros like this
%let elenco = gen feb mar apr giu;
%macro export;
%local i;
%let i = 0;
%do %until (%scan(&elenco,&i+1) = );
%let i = %eval(&i+1);
%let ele=%scan(&elenco,&i);
data month_&i;
set tot;
where month="&ele";
run;
proc export data = month_&i
outfile = "C:\prova_&i.xls"
dbms = excelcs replace;
sheet="month_&i";
run;
%end;
Thanks in advance
Ods excel does not work well with big datasets. But it could be worth a try.
* Sort by your sheet-variable ;
proc sort data=sashelp.class out=work.class;
by age;
run;
ods excel
file='c:\temp\mult_sheet.xlsx'
options(sheet_interval='output' sheet_name='#byval1');
proc print data=work.class label noobs;
by age;
run;
ods excel close;

SAS: dataset name Remove the date and replace with the current date

I currently have a macro which moves my dataset from one branch to another. In each movement, the date is updated. However, I am having trouble with removing the old date autonomously before inputting the new date, any advice?
The code is:
%Macro Merge_Branch(Branch = , Filename = , Library = );
%Let Timestamp = %sysfunc(putn(%sysfunc(date()),yymmddn8.));
%if &Branch. = Latest_Commit %then %do;
Data LC._&Timestamp._&Filename.;
set &Library..&Filename.;
run;
%end;
%else %if &Branch. = Staging %then %do;
%Let Filename = _20180909_Financial_Input;
%Let Filename_temp = %scan(&Filename.,2,'_');
%Let Date_String = %scan(&Filename.,1,'_');
/* this is the section where I get stuck the dash is a subtraction i.e. I want to remove the date and just have the string*/
%Let Filename_Stg = &Filename_temp - &Date_String;
Data Stg._&Timestamp._&Filename_Stg.;
set LC.&Filename.;
run;
%end;
%mend;
Input data can be made like this
data LC._20180909_Financial_Input;
var var1;
datalines;
1
1
1
1
;
run;
%Macro Merge_Branch(Branch = Staging , Filename = Financial_Input, Library = LC );
/*Note, in this macro the library is not important because it will always move from LC to STG*/
Your new file name is resolving to this.
Data Stg._20181009_Financial - 20180909;
That is not a SASNAME.

counting observations in sas

I have case data of TB with the following variables: age, case_status, city, year, month, and race from the past 11 years (2006-2017). I would like to make a line graph of month by year with cases as the y axis, month as the x axis, and then a new line for each year. But I am unsure how to count the observations. I am new with sas so I apologize in advance if I am doing this wrong but this is what I had in mind:
PROC SORT DATA= TB
BY YEAR;
RUN;
DATA YEAR;
SET TB;
COUNT + 1;
BY YEAR;
IF FIRST.YEAR THEN COUNT =1;
RUN;
PROC SGPLOT DATA = YEAR;
SERIES X = Month Y = COUNT;
SERIES X = Year Y = COUNT;
TITLE 'Temporal Patterns of TB from 2006-2017';
RUN;
However I am getting a blank output with this code.
Any feedback/help would be greatly appreciated!
Thank you in advance!
This is much easier if you provide sample data. Assuming you're trying to do something similar to graphing a line chart, I'll use the SASHELP.PRDSALE data set as a demo. I use the weight statement here to add up the amounts but you won't need that.
First run PROC FREQ to get the summary statistics and then use the output from that in SGPLOT to get the graph. Your SG code is close.
proc freq data=sashelp.prdsale noprint;
table year*month / out=summary_stats;
weight actual;
run;
proc sgplot data=summary_stats;
series x=month y=count / group=year;
run;
There are a variety of groupings, bys, or panelbys that might better communicate or better present the count variations of each year.
For example
data have (label="Disease cases");
do casedate = '01jan2006'd to '31dec2017'd;
year = year(casedate);
month = month(casedate);
do day_n = 1 to 30*ranuni(123);
case_status = floor(4*ranuni(123));
city_id = ceil(100*ranuni(123));
race = ceil(6*ranuni(123));
output;
end;
end;
run;
proc means noprint data=have;
class year month;
types year*month;
output out=counts n=freq;
run;
data counts;
set counts;
yearmo = mdy(month,1,year);
format yearmo yymmd7.;
run;
options orientation=landscape papersize=a4;
ods html close;
ods html;
proc sgplot data=counts;
series x=month y=freq / group=year;
xaxis type=discrete;
where _type_ = 3;
run;
proc sgplot data=counts;
series x=yearmo y=freq / group=year;
xaxis type=discrete display=(novalues);
where _type_ = 3;
run;
proc sgplot data=counts;
by year;
series x=yearmo y=freq / group=year;
xaxis type=discrete ;
where _type_ = 3;
run;
proc sgpanel data=counts;
panelby year;
series x=month y=freq ;
colaxis type=discrete;
where _type_ = 3;
run;
proc sgpanel data=counts;
panelby year / columns=4 ;
series x=month y=freq ;
colaxis type=discrete display=(novalues);
where _type_ = 3;
run;

Recursively add to a data table in SAS

I am new to SAS. I need to do x-iterations to populate my dataset called MYRS.
Each iteration needs to JOIN TABLE1 with (TABLE2+ MYRS) MINUS the records which are already in MYRS table.
Then, I need to update MYRS table with additional matches. The GOAL is to track a chain of emails.
MYRS is essentially a copy of TABLE1 and contains matching records. Kind of tricky. (simplified schema). Table1 Can have DUPS.
For example
TABLE1:
ID | EMAIL1 | EMAIL2 | EMAIL3 | EMAIL4|
1 | A | s | d | F
2 | g | F | j | L
3 | z | x | L | v
4 | z | x | L | v
2 | g | F | j | L
TABLE2:
EMAIL
A
MYRS (starts as empty dataset)
EMAIL1 | EMAIL2 | EMAIL3 | EMAIL4
Logic: TABLE1 has email that matches email in TABLE2. Therefore this record need to show up. Other records don't match anything in TABLE2. But because Record1 and Record2 share the same ALTERNATIVE email F, Record2 also need to be shown. But because Record2 and Record3 share same alternative email L, Record3 also needs to be shown. And so fourth...
proc sql;
SELECT TABLE1.id,
TABLE1.email1,
TABLE1.email2,
TABLE1.email3,
TABLE1.email4
FROM TABLE1
INNER JOIN (
SELECT EMAIL
FROM TABLE2
UNION
SELECT EMAIL1 AS EMAIL
FROM MYRS
UNION
SELECT EMAIL2 AS EMAIL
FROM MYRS
UNION
SELECT EMAIL3 AS EMAIL
FROM MYRS
UNION
SELECT EMAIL4 AS EMAIL
FROM MYRS
)
ON EMAIL=EMAIL1 OR EMAIL=EMAIL2 OR EMAIL=EMAIL3 OR EMAIL=EMAIL4
WHERE TABLE1.id NOT IN (
SELECT DISTINCT ID
FROM MYRS
)
quit;
How can I create the following logic:
Wrap this into some sort of function
Before sql execution, count amount of records in MYDS and SAVE the count
Execute SQL and update MYDS
Count amount of records in MYDS
If MYDS count did not change, stop execution
Else, goto #3
I am very new to SAS (3 days to be exact) and trying to put everything together. (I would use the logic above if I was to do that in Java)
Here is a macro approach, it mostly follows your logic but transforms your data first and the input/output is a list of IDs (you can easily get to and from emails with this).
This code will probably introduce quite a few SAS features that you are unfamiliar with, but the comments and explanations below should help . If any of it is still unclear take a look at the links or add a comment.
It expects input data:
inData: Your TABLE1 with ID and EMAIL* variables
matched: An initial list of known wanted IDs
It returns:
matched: An updated list of wanted IDs
/* Wrap the processing in a macro so that we can use a %do loop */
%macro looper(maxIter = 5);
/* Put all the emails in one column to make comparison simpler */
proc transpose data = inData out = trans (rename = (col1 = email));
by ID;
var email:;
run;
/* Initialise the counts for the %where condition */
%let _nMatched = 0;
%let nMatched = 1;
%let i = 0;
/* Loop until no new IDs are added (or maximum number of iterations) */
%do %while(&_nMatched. < &nMatched. and &i < &maxIter.);
%let _nMatched = &nMatched.;
%let i = %eval(&i. + 1);
%put NOTE: Loop &i.: &nMatched. matched.;
/* Move matches to a temporary table */
proc datasets library = work nolist nowarn;
delete _matched;
change matched = _matched;
quit;
/* Get new matched IDs */
proc sql noprint;
create table matched as
select distinct c.ID
from _matched as a
left join trans as b
on a.ID = b.ID
left join trans as c
on b.email = c.email;
/* Get new count */
select count(*) into :nMatched from matched;
quit;
%end;
%mend looper;
%looper(maxIter = 10);
The interesting bits are:
proc transpose: Converts the input into a deep table so that all the email addresses are in one variable, this makes writing the email comparison logic simpler (less repetition needed) and puts the data in a format that will make it easier for you to clean the email addresses if necessary (think upcase(), strip(), etc.).
%macro %mend: The statements used to define a macro. This is necessary as you cannot use macro logic or loops in open code. I've also added an argument so you can see how that works.
%let and select into :: Two ways to create macro variables. Macro variables are referenced with the prefix & and are used to insert text into the SAS program before it is executed.
%do %while() %end: One of the ways to perform a loop within a macro. The code within will be run repeatedly until the condition evaluates to false.
proc datasets: A procedure for performing admin tasks on datasets and libraries. Used here to delete and rename temporary tables.

SAS exclude variables from selection in dictionary columns

I need to do a loop over a list of variables but excluding some of those.
I wanted to add a prefix to each variable except for those.
I wrote a macro:
%macro addprefijo(tabla);
proc contents data = labo2.&tabla.;
title 'before renaming'; run;
proc sql;
select nvar into :num_vars
from dictionary.tables
where libname='LABO2' and memname="&tabla";
%put 'num_vars' &num_vars;
select distinct(name) into :var1-:var%trim(%left(&num_vars))
from dictionary.columns
where libname='LABO2' and memname="&tabla" /*and name not in ('cid', 'COUNTY', 'ESTADO') */;
quit;
proc datasets library=LABO2;
modify &tabla;
rename
%do i=1 %to &num_vars.;
&&var&i = &tabla._&&var&i.
%end;
;
quit;
run;
proc contents data=LABO2.&tabla.;
title' after renaming';
run;
%mend;
%addprefijo(A_CLI);
I tried what is commented but crashes and with out it adds the prefix to all the variables. Those 3 variables are not in all the tables.
How can I solve it?
Thanks
The following should work. Using proc contents out = rather than dictionary tables. Also using the sql separated by syntax to create a space separated list of variables rather than indervidual indexed variables.
%macro addprefijo(tabla);
proc contents
data = labo2.&tabla.
out = _a_contents
noprint;
run;
proc sql noprint;
select NAME
into :vars separated by " "
from _a_contents
where NAME not in ('cid', 'COUNTY', 'ESTADO');
quit;
proc datasets library = labo2;
modify &tabla.;
rename
%do i = 1 %to %sysfunc(countw(&vars., %str( )));
%let var = %scan(&vars., &i., %str( ));
&var. = &tabla._&var.
%end;;
quit;
%mend;
%addprefijo(A_CLI);

Resources