02-04-2025
Haris
Lapis Lazuli | Level 10
Member since
06-23-2011
- 239 Posts
- 39 Likes Given
- 13 Solutions
- 54 Likes Received
-
Latest posts by Haris
Subject Views Posted 662 02-04-2025 03:52 PM 680 02-04-2025 03:22 PM 729 02-04-2025 01:07 PM 865 02-03-2025 06:24 PM 880 02-03-2025 06:14 PM 893 02-02-2025 02:35 PM 913 02-02-2025 01:05 PM 1055 02-01-2025 04:35 PM 510 01-28-2025 04:29 PM 2774 02-05-2024 11:00 AM -
Activity Feed for Haris
- Posted Re: Conditional %IF %THEN processing as a macro parameter on SAS Programming. 02-04-2025 03:52 PM
- Posted Re: Conditional %IF %THEN processing as a macro parameter on SAS Programming. 02-04-2025 03:22 PM
- Posted Re: Conditional %IF %THEN processing as a macro parameter on SAS Programming. 02-04-2025 01:07 PM
- Posted Re: Conditional %IF %THEN processing as a macro parameter on SAS Programming. 02-03-2025 06:24 PM
- Posted Conditional %IF %THEN processing as a macro parameter on SAS Programming. 02-03-2025 06:14 PM
- Posted Re: Scoring Mixed Bayesian Model on Statistical Procedures. 02-02-2025 02:35 PM
- Posted Re: Scoring Mixed Bayesian Model on Statistical Procedures. 02-02-2025 01:05 PM
- Liked Re: Scoring Mixed Bayesian Model for webart999ARM. 02-02-2025 12:44 PM
- Posted Scoring Mixed Bayesian Model on Statistical Procedures. 02-01-2025 04:35 PM
- Posted Re: Bayesian Analysis and PROC IML: What's the Score? on SAS Communities Library. 01-28-2025 04:29 PM
- Liked Re: Increase variable name length from 32 to 128 characters for alecwh22. 05-24-2024 12:24 PM
- Posted Re: Read data from MS-SQL into SAS via SAS/ACCESS ODBC on SAS Programming. 02-05-2024 11:00 AM
- Posted Re: Read data from MS-SQL into SAS via SAS/ACCESS ODBC on SAS Programming. 02-04-2024 01:31 PM
- Posted Re: Read data from MS-SQL into SAS via SAS/ACCESS ODBC on SAS Programming. 02-03-2024 06:13 PM
- Posted Re: Read data from MS-SQL into SAS via SAS/ACCESS ODBC on SAS Programming. 02-03-2024 06:11 PM
- Posted Read data from MS-SQL into SAS via SAS/ACCESS ODBC on SAS Programming. 02-03-2024 05:32 PM
- Posted Re: Integrating over a non-normal distribution on SAS/IML Software and Matrix Computations. 10-21-2023 08:56 AM
- Got a Like for Re: Integrating over a non-normal distribution. 09-15-2023 05:01 AM
- Posted Re: Integrating over a non-normal distribution on SAS/IML Software and Matrix Computations. 09-14-2023 05:21 PM
- Liked Re: Integrating over a non-normal distribution for Rick_SAS. 09-14-2023 05:21 PM
-
Posts I Liked
Subject Likes Author Latest Post 1 13 1 3 1 -
My Liked Posts
Subject Likes Posted 2 09-14-2023 05:21 PM 2 09-14-2023 01:38 PM 1 02-09-2022 01:25 PM 1 05-06-2015 12:53 PM 9 04-07-2020 12:13 PM
02-04-2025
03:52 PM
Yes, indeed! A dataset for various code combination is something we're looking into as well. The combinations we need to cover are quite extensive!
Some times its as simple as CC1 = A & B. That is, if a patient has A and B the she meets criteria for CC1. Slightly more complicated CC2 = A & IN (B, C). Other times all three are required and it's CC3 = A & B & C. And then you get two but not the third for CC4 = A & B & (NOT C). And so on, and so on, and so on with about 200 base codes combining every which way two, three, four, ... fifteen at a time.
Thank you for your input!
... View more
02-04-2025
03:22 PM
Thanks, Tom. Appreciate your continued effort to help me with this.
As to the WHY? I have (sometimes long) lists of codes that vary usually by one code. As I explained in the original post, I am trying to avoid re-typing these lists. Say I have 15 codes for DV=6 and those same 15 plus one more for DV=5. I'm trying to add that one code conditionally on the value of DV without the need to re-type. The lists are also changing all the time so, when a change happens, I don't want to edit the list in multiple places.
I've entertained the idea of using %LET macro variable assignments but there are dozens of these lists many with permutation. I am afraid that a code with &MacroVariables would become even less readable.
Hope that helps you understad the puruit here. Thanks again.
... View more
02-04-2025
01:07 PM
Thanks for your attention and input, Tom.
I realize now that my post contained too much unnecessary detail irrelevant to the question I am asking. The fact that I renamed variable DV to DataVrsn when trying to fix the line-break issues did not help matters at all.
Thanks, for straightening up the fact that you CANNOT use variable values in the %IF %THEN conditional processing. Not the way I am trying to go about it anyway. But, in the end, that's what I am trying to accomplish: change a list that is evaluated by the <VarName> IN (Value1, ..., ValueN) statement conditional on the value of the DataVrsn variable. Hope this code will illustrate it better: what I need is variable CC123. What I am hoping to do is to eliminate redundant typing of both redundant THEN and ELSE conditions and replace them with a conditional processing that adds a value to the list.
%macro runSQL();
proc sql;
select Pt, Proc, DataVrsn,
case when DataVrsn<6 then max(Proc IN (1)) AND max(Proc IN (2 ))
else max(Proc IN (1)) AND max(Proc IN (2 3)) end AS CC123,
max(Proc IN (1)) AND max(Proc IN (2 %if DataVrsn LT 6 %then %do; 3 %end; )) AS ConditionalCC123
from x
group by Pt
order by Pt, Proc
;
quit;
%mend runSQL;
%runSQL;
... View more
02-03-2025
06:24 PM
Sorry, I can't insert line-breaks for some reason. The DATA step ignores them 😞
... View more
02-03-2025
06:14 PM
I am looking to modify macro parameters using %IF %THEN conditional macro language. Unfortunately, conditional macro language cannot be used as part of another macro's parameter specification.
This community has been an invaluable resource. Can I ask for ideas how to proceed? I know I can do CASE WHEN and condition it on variable DV that way; however, the lists can be long and differ by one number most of the time. I'd hate to type them out twice and open the door for errors in the future edits.
In the example below, both Pt 1 and 2 should get value 1=Yes while both Pt 3 and 4should get 0=No.
- Pt=1 has both Proc=1 and Proc=2.
- Pt=2 has Proc=1 and (Proc=3 AND DV<6)
- Pt=3 has Proc=1 and Proc=3 but DV>6.
- Pt=4 has Proc=1 but no Proc=2 OR Proc=3 even though DV<6.
data x; input Pt Proc DataVrsn @@; cards; 1 1 6 1 2 6 1 4 6 2 1 5 2 3 5 2 5 5 3 1 7 3 3 7 3 5 7 4 1 4 4 4 4 4 5 4 ; run;
%macro CC(PL1,PL2,PL3,PL4);
max(Proc IN (&PL1)) AND max(Proc IN (&PL2))
%if &PL3>0 %then %do; AND max(Proc IN (&PL3)) %end;
%if &PL4>0 %then %do; AND max(Proc IN (&PL4)) %end;
%mend CC;
options mPrint mLogic SymbolGen;
proc sql;
select Pt,
%CC(1,2 %if DV LT 6 %then %do; 3 %end; ) as CC12_3
from x
group by Pt
;
quit;
... View more
02-02-2025
02:35 PM
Benchmarking results are in:
1. My original code ran just a tad over two hours
2. My new and improved code without vValueX() or sorting improved significantly to 1.5 hours.
3. PROC IML method recommended above blew them both out of the water completing the task in 24.5 minutes!
Thanks for playing!
... View more
02-02-2025
01:05 PM
Brilliant! Thanks so much. Will test the performance of this code.
In the meantime, I was able to shave off more than 30% of execution time by (1) removing the use of vValueX() lookup and (2) eliminating interim PROC SORTs. I replaced the former with TRANSPOSE step for Random Intercepts and the latter with a PROC SQL step for merging instead of DATA step. A lot less code too:
*** 2.a TRANSPOSE PT DATA to TALL AND MERGE WITH FLAT RANDOM INTERCEPTS ;
proc transpose data=Pt out=Pt_T( rename=(Col1=mLP) ); by ParticID PtID; var mLR_Iter:;
*** 2.b TRANSPOSE RI DATA to TALL AND MERGE WITH TALL PATIENTS ;
proc transpose data=RI out=RI_T( rename=(Col1=RI) ); by Iteration; var RI:;
*** 3. NO-SORT SQL MEGE ;
proc sql; create table WantM3 as
select p.ParticID, PtID, Iteration, mLP, RI, mLP+RI as cLP
from Pt_T p
left join RI_T r ON input(substr(p._NAME_,9),best.) = r.Iteration
AND p.ParticID = input(substr(r._NAME_,7),best.)
order by p.ParticID, PtID, Iteration
;
quit;
... View more
02-01-2025
04:35 PM
Thanks to Danny for this wonderful resource on how to score a fixed effects logistic Bayesian model: https://communities.sas.com/t5/SAS-Communities-Library/Bayesian-Analysis-and-PROC-IML-What-s-the-Score/ta-p/923044.
I need to take this one step further and add random intercepts to the process. My IML skills need serious work so I had to take the output of the fixed effect scoring out of PROC IML, transpose them to create one tall file and then merge it with the Iteration by RandomIntercept matrix in the OutPost file from MCMC/BGLIMMIX. I use vValueX() function to match each Level 2 ID to the corresponding column in the Random Intercept dataset.
This workflow is straightforward with relatively light code. Maybe someone can use it as is. For my purposes it's too SLOW! I am working with over 1,000 Level 2 units containing over 500 Level 1 Units each and 5,000 iterations seems like a minimum for Bayesian output. Marginal Linear Predictor (mLP) takes seconds to compute even for this large dataset in PROC IML. Adding Random intercepts to each mLP estimate to obtain Conditional Linear Predictors takes hours. I am in an evironment where I need to do this on a regular basis for dozens of models so the time adds up very quickly. I am hoping some good soul can translate what I have done with transpose/merge into PROC IML and that matrix addition can shave serious time off the process. Thanks in advance.
Simulated source data files and the workflow to add ConditionalLP = mLP + RI_L2 are in the code below. L12 dataset is what comes out from the scoring effort in the blog reference above (minus the L2 unit IDs).
%let nL2 = 10; * Level 2 units ;
%let nL1 = 20; * L1 units per L2 unit on average ;
%let nIter = 50; * MCMC iterations ;
data L12;
do L2ID=1 to &nL2;
do L1ID=1 to ceil(RanUni(1)*&nL1*2); * simulate variable number of L1 units per L2 unit ;
array mLR_Iter[&nIter]; do i=1 to &nIter; mLR_Iter[i] = RanNor(1); end;
output;
end;
end;
drop i;
data OutPost; * Random Intercepts: one row per MCMC Iteration, one column per L2 unit ;
do Iteration=1 to &nIter;
array RI_L2[&nL2]; do i=1 to &nL2; RI_L2[i] = RanNor(1);end;
output;
end;
drop i;
run;
*** 2. TRANSPOSE PT DATA to TALL AND MERGE WITH RANDOM INTERCEPTS ;
proc transpose data=L12 out=L12_Tall;
by L2ID L1ID;
var mLR_Iter:;
proc sql;
create table L12_Tall as
select input(substr(_Name_,9),best.) as Iteration, /* extract Iteration ID that starts with character 9 */
L2ID, L1ID, Col1 as mLP /* marginal linear predictor */
from L12_Tall
order by Iteration, L2ID, L1ID
;
quit;
data WantM;
merge L12_Tall
OutPost;
by Iteration;
ConditionalLP = mLP + vValueX(cats('RI_L2',L2ID));
drop RI_L2:;
run;
... View more
01-28-2025
04:29 PM
Thanks for this Danny. Do you have a version for mixed models with random effects? What you have here works wonderfully for marginal predicted probabilities. How about conditional ones that include the random intercept for each level 2?
Thanks,
Haris
... View more
02-05-2024
11:00 AM
CULPRIT FOUND!
Thank you all for the input. I've used some of the proposed ideas and will try the rest too.
SAS MISSING() in the WHERE statement was causing the failure to pass the querry to DBMS for fetching data! As soon as I replaced the commented out code that contains "missing()" with equivalent "is missing" syntax, no more memory hogging on the WORK folder and execution in seconds rather than >30 minutes.
where SurgDt between '01Oct2022'd and '30Sep2023'd
and Age >= 18
and CountryUS = 'Y'
/*** and missing(ExpiredInOR) */
/*** and not( (missing(OpValve) or OpValve = '2') */
/*** and (missing(OpCAB) or OpCAB = '2') ) */
and ExpiredInOR is missing
and not( (OpValve is missing or OpValve = '2')
and (OpCAB is missing or OpCAB = '2') )
Any input on MISSING() function? Weird, isn't it?
As to how I knew that SAS was importing the data: the original querry would (1) take way too long to retrieve <50 rows of data and (2) the memory on the c:\ drive would disappear like rain in the desert while the query was executing. I have well over 0.5TB on the main drive and it would all get gobbled up by SAS. No way a dataset with <50 rows and <200 columns consumes >700GB of memory.
... View more
02-04-2024
01:31 PM
Straight up SAS date ‘ddmmmyyyy’d, and two numbers — an age and a category number for a status.
... View more
02-03-2024
06:13 PM
Updated Query -- hope it's more clear this way:
proc sql;
create table want as
select a.<VarList>, b.<VarList>, c.<VarList>
from MySQL.MSSQL_A as a
inner join MySQL.MSSQL_B as b ON a.IDVarA=b.IDVarB
inner join MySQL.MSSQL_C as c ON a.IDVarA=c.IDVarC
where a.SurgDate > x
AND b.Age > y
AND c.Status = z
;
quit;
... View more
02-03-2024
06:11 PM
Fair. I used shortcuts that I thought were obvious.
libname MySQL ODBC dsn=MySQL schema=DBO;
MySQL is defined as an ODBC Data Source 64-bit via ODBC Driver 17 for SQL Server.
Each table in the FROM clause is MySQL.TableA, MySQL.TableB and MySQL.TableC.
I don't think I am doing a cartesian join as column ID is a unique row identifier and each table contains exactly the same number of rows for each patient/ID in the database. The WHERE clause is meant to highlight the fact that Surgery Date is one table, Patient Age is in anotehr, and Patient Status is the third table. I want only a small SurgDate range, Patients of a certain Age, and Status. Hence the three WHERE conditions. I think using the same name Variable for all three is misleading -- they are all three different variables in each table. The WHERE clause is not meant to eliminate cartesian joint like it is often used.
I agree with you, this code is relatively simple and should be executed on the server by default. But it is not! WHY?
... View more
02-03-2024
05:32 PM
I am reading from a large MS-SQL database that's split into three separate tables due to column limitation. I only have SAS/ACCESS ODBC -- no specific SQL driver.
The PROC SQL joins the three tables (all of them have identical unique rowIDs) and filters the intake with the WHERE clause. Unfortunately, it appears that SAS reads all three tables in full and merges them on my desktop.
Here's the code:
proc sql;
create table want as
select a.<VarList>, b.<VarList>, c.<VarList>
from MSSQL_A as a
inner join MSSQL_B as b ON a.ID=b.ID
inner join MSSQL_C as c ON a.ID=c.ID
where a.Variable = x
AND b.Variable = y
AND c.Variable = z
;
quit;
The source tables have millions of records and thousands of columns; however, the query only returns a handful of rows after where-filter and about a hundred columns that are manually listed in the SELECT clause.
Looking for advice on how to make this more efficient. It takes way too long to read all the data into SAS and I even run out of room on the disk. How can I push the filtering task from SAS to the server? Will pass-through method work on MS-SQL database if I only have ODBC driver? Is it worth purchasing SAS/ACCESS for SQL specifically? I used to work with SAS/ACCESS ORACLE and that shaved of a lot of time. New to ODBC/MS-SQL. Should I import the three tables into SAS separately, filtering each as best as I can, and then join them in SAS?
... View more
10-21-2023
08:56 AM
Closing parenthesis got included in the link. Remove it and the link works. Just checked. <> [12874.jpg] A note on obtaining correct marginal predictions from a random intercepts model for binary outcomes - BMC Medical Research Methodology<> bmcmedresmethodol.biomedcentral.com<>
... View more