Turn on suggestions

Auto-suggest helps you quickly narrow down your search results by suggesting possible matches as you type.

Showing results for

Options

- RSS Feed
- Mark Topic as New
- Mark Topic as Read
- Float this Topic for Current User
- Bookmark
- Subscribe
- Mute
- Printer Friendly Page

☑ This topic is **solved**.
Need further help from the community? Please
sign in and ask a **new** question.

- Mark as New
- Bookmark
- Subscribe
- Mute
- RSS Feed
- Permalink
- Report Inappropriate Content

Posted 07-08-2023 03:17 PM
(440 views)

Hi SAS community

I have data over time for ~200 participants. For each participant, I want to fit the same model, but I have a different set of initial conditions for the PROC NLIN routine (derived by looking at data for each paritcipant). How do I get this to work (code below)? Any help really appreciate. I keep get error like this:

NOTE: DER.a not initialized or missing. It will be computed automatically.

NOTE: DER.b not initialized or missing. It will be computed automatically.

NOTE: DER.c not initialized or missing. It will be computed automatically.

NOTE: DER.d not initialized or missing. It will be computed automatically.

WARNING: Zero observations could be evaluated.

NOTE: The data set WORK.PARAMS_OUT_4 has 0 observations and 9 variables.

```
data initial_params;
set in.initial_params;
nf+1;
call symputx("last_nf",nf);
run;
data participant_data;
set in.participant_data;
run;
%macro fit;
%do j=1 %to &last_nf.;
data _null_;
set initial_params;
where nf=&j;
call symputx("beta10",beta10);
call symputx("beta20",beta20);
call symputx("beta30",beta30);
```

call symputx("beta40".beta40);
call symputx("participant",subject);
run;
proc nlin data = participant_data g4 plots = fit maxiter = 50 outest = params_out_&j.;
where subject="&participant";
parameters a = &beta10. &beta20. = -3 c = &beta30. d = &beta40.;
model response = a*exp(time/b) + c*time + d;
run;
%end;
%mend;
%fit;

suggesting what I do wrong would be very helpful to me!

1 ACCEPTED SOLUTION

Accepted Solutions

- Mark as New
- Bookmark
- Subscribe
- Mute
- RSS Feed
- Permalink
- Report Inappropriate Content

Hi @linlin87,

First of all, I see two syntax errors in your code which would prevent the PROC NLIN step from even producing the messages you show:

- The period between "beta40" and beta40 in the fourth CALL SYMPUTX of the DATA _NULL_ step must be a comma.
- Instead of &beta20. = -3 in the PARAMETERS statement I would rather expect something like b = &beta20. (or does macro variable BETA20 contain a variable name such as b?).

One situation in which the warning "Zero observations could be evaluated" would occur is that the WHERE condition subject="&participant" is not met for any observation of dataset PARTICIPANT_DATA. So, make sure that those character values match exactly.

But most importantly, I think you could both simplify your program and make it more robust if you used a single PROC NLIN step with a BY statement (by subject) instead of the macro, macro variables and the WHERE condition. Then you could name the dataset containing the subject-specific initial parameter values in the PDATA= option of the PARAMETERS statement. See the syntax and section "Assigning Starting Values from a SAS Data Set" in the PROC NLIN documentation.

Edit: Below is an example of what your PROC NLIN step could look like. Note the structure of the PDATA= dataset (which I named init_params).

```
/* Create test data for demonstration */
data temp;
input subject a b c d;
cards;
1 8 2 0.2 1
2 7 1 0.3 -1
;
proc transpose data=temp out=init_params(rename=(col1=estimate)) name=parameter;
by subject;
run;
data participant_data(drop=a--d);
set temp;
do time=1 to 5;
response=a*exp(time/b) + c*time + d + rannor(1);
output;
end;
run;
/* Use BY-group processing and the PDATA= option in PROC NLIN */
proc nlin data = participant_data g4 plots = fit maxiter = 50 outest = params_out;
by subject;
parameters / pdata=init_params;
model response = a*exp(time/b) + c*time + d;
run;
```

3 REPLIES 3

- Mark as New
- Bookmark
- Subscribe
- Mute
- RSS Feed
- Permalink
- Report Inappropriate Content

Hi @linlin87,

First of all, I see two syntax errors in your code which would prevent the PROC NLIN step from even producing the messages you show:

- The period between "beta40" and beta40 in the fourth CALL SYMPUTX of the DATA _NULL_ step must be a comma.
- Instead of &beta20. = -3 in the PARAMETERS statement I would rather expect something like b = &beta20. (or does macro variable BETA20 contain a variable name such as b?).

One situation in which the warning "Zero observations could be evaluated" would occur is that the WHERE condition subject="&participant" is not met for any observation of dataset PARTICIPANT_DATA. So, make sure that those character values match exactly.

But most importantly, I think you could both simplify your program and make it more robust if you used a single PROC NLIN step with a BY statement (by subject) instead of the macro, macro variables and the WHERE condition. Then you could name the dataset containing the subject-specific initial parameter values in the PDATA= option of the PARAMETERS statement. See the syntax and section "Assigning Starting Values from a SAS Data Set" in the PROC NLIN documentation.

Edit: Below is an example of what your PROC NLIN step could look like. Note the structure of the PDATA= dataset (which I named init_params).

```
/* Create test data for demonstration */
data temp;
input subject a b c d;
cards;
1 8 2 0.2 1
2 7 1 0.3 -1
;
proc transpose data=temp out=init_params(rename=(col1=estimate)) name=parameter;
by subject;
run;
data participant_data(drop=a--d);
set temp;
do time=1 to 5;
response=a*exp(time/b) + c*time + d + rannor(1);
output;
end;
run;
/* Use BY-group processing and the PDATA= option in PROC NLIN */
proc nlin data = participant_data g4 plots = fit maxiter = 50 outest = params_out;
by subject;
parameters / pdata=init_params;
model response = a*exp(time/b) + c*time + d;
run;
```

- Mark as New
- Bookmark
- Subscribe
- Mute
- RSS Feed
- Permalink
- Report Inappropriate Content

Thank you @FreelanceReinh !!

One more questions for you. Now I have this

```
proc nlin data = participant_data g4 plots = fit maxiter = 50 outest = params_out;
by subject;
parameters / pdata=init_params;
model response = a*exp(time/b) + c*time + d;
run;
```

but actually I need that a+d = value. So:

```
proc nlin data = participant_data g4 plots = fit maxiter = 50 outest = params_out;
by subject;
parameters / pdata=init_params;
bounds d+a = value;
model response = a*exp(time/b) + c*time + d;
run;
```

Note that value is different for each SUBJECT. How do I do?

- Mark as New
- Bookmark
- Subscribe
- Mute
- RSS Feed
- Permalink
- Report Inappropriate Content

You're welcome.

I think the BOUNDS statement is more suitable for constraints in the form of *inequalities* about the parameters. Given that all these numbers are non-integers, an *exact* equality such as d+a=value would be a risky requirement anyway. (Note that, e.g., 0.1+0.2 ne 0.3 in Windows SAS due to rounding errors in the binary system.) Also, the BOUNDS statement, unlike the PARAMETERS statement, does not allow for varying values coming from a dataset. There is a different procedure, PROC HPNLMOD, which offers a RESTRICT statement where you could specify your linear constraint. But I have never used PROC HPNLMOD before today, so let's stay with PROC NLIN.

In PROC NLIN it's probably better to implement the constraint d+a=value in the model equation. You have two options for that: Either replace d with value-a, or replace a with value-d. Let's follow the first approach, i.e., *eliminate* parameter d in the model equation and introduce value as a new variable (not parameter) in the input dataset participant_data.

Here is the example from my earlier post, with the new constraint implemented. Changes are highlighted in blue.

/* Create test data for demonstration */ data temp; input subject a b cvalue;/* parameter d has been eliminated by the constraint d+a=value */cards; 1 8 2 0.292 7 1 0.36; proc transpose data=temp(drop=value)out=init_params(rename=(col1=estimate)) name=parameter; by subject; run; data participant_data(drop=a--c); set temp; do time=1 to 5; response=a*exp(time/b) + c*time +value - a+ rannor(1); output; end; run; /* Use BY-group processing and the PDATA= option in PROC NLIN */ proc nlin data = participant_data g4 plots = fit maxiter = 50 outest = params_out; by subject; parameters / pdata=init_params; model response = a*exp(time/b) + c*time +value - a; run;

As you can see in dataset participant_data, variable value is a subject-dependent constant over time. Parameters a, b, c are estimated, starting with (unchanged) subject-specific initial values from dataset init_params, as before. For each subject, you could use the estimate for parameter a computed by PROC NLIN and the known value of variable value to compute d = value - a, if needed:

```
data est(drop=_:);
set params_out;
where _type_='FINAL';
run;
data values;
set participant_data(keep=subject value);
by subject;
if first.subject;
run;
data want;
merge values est;
by subject;
d=value-a;
run;
```

Obviously, the estimates will satisfy the constraint a+d = value, possibly up to tiny rounding differences like 1E-16 as in this example:

138 data _null_; 139 d=0.9-0.3; 140 if 0.3+d ne 0.9 then put 'Surprised?'; 141 delta=0.3+d-0.9; 142 put delta=; 143 run; Surprised? delta=1.110223E-16

Registration is open! SAS is returning to Vegas for an AI and analytics experience like no other! Whether you're an executive, manager, end user or SAS partner, SAS Innovate is designed for everyone on your team. Register for just $495 by 12/31/2023.

**If you are interested in speaking, there is still time to submit a session idea. More details are posted on the website. **

5 Steps to Your First Analytics Project Using SAS

For SAS newbies, this video is a great way to get started. James Harroun walks through the process using SAS Studio for SAS OnDemand for Academics, but the same steps apply to any analytics project.

Find more tutorials on the SAS Users YouTube channel.