|
Listerees, I’m brand new to macros. I’m trying to translate
some sas into spss. I have 21 vectors. Let’s say I have a vector named
vars1 composed of var1 var2 var3. I want to say if var1 = 1, then make
var2 and var3 = 0. The vectors are of varying lengths. So my macro so far looks like this. Two main
questions:
DEFINE !varnum(). !DO !I = 1 !TO 21. loop #I = 1 to THIS NUMBER VARIES DEPENDING ON VECTOR. loop if (vars!I(#I)=1).
compute vars!I(#I+1) = 0. end loop if (#I = 6). end loop. exe. !DOEND. !ENDDEFINE. Any help is as always mucho appreciated! Thanks Matt Matthew Pirritano, Ph.D. Research Analyst IV Medical Services Initiative (MSI) Orange County Health Care Agency (714) 568-5648 |
|
Dear Matthew,
I'm pretty new to macros as well but as far as my knowledge goes, there's two types of macro loops: index and list processing loops. For an index loop, the number of loops depends on the !to statement. The numbers surrounding this !to statement can be macro arguments in order to increase flexibility. For a list processing loop, the number of elements in the list determines the number of loops. As far as I know, the macro will be unaware that a variable list containing [bli bla blo] has length = 3 but I think you could assign this 3 to an argument within the macro by a somewhat complicated construction. But I think that's not what you need. I enclosed two examples of macro loops, I hope you find them useful, if not, let us know, OK? Best of luck! Ruben van den Berg Methodologist TNS NIPO P: +31 20 522 5738 data list free/id. begin data 1 2 3 4 5 end data. *Index loop. define !example_1 (start=!tokens (1) /end=!tokens (1)) !do !i =!start !to !end comp !con("var",!i)=!i. !doend !enddefine. !example_1 start=1 end=21. exe. *List processing loop. define !example_2 (vars !cmdend ) !do !x !in (!vars) comp !x=!x * 10. !doend !enddefine. !example_2 vars=var1 var2 var3 var4 var5 var6 var7 var8 var9 var10 var11 var12 var13 var14 var15 var16 var17 var18 var19 var20 var21 . exe. Date: Thu, 1 Apr 2010 11:28:17 -0700 From: [hidden email] Subject: looping in a macro To: [hidden email] Listerees,
I’m brand new to macros. I’m trying to translate some sas into spss.
I have 21 vectors. Let’s say I have a vector named vars1 composed of var1 var2 var3. I want to say if var1 = 1, then make var2 and var3 = 0.
The vectors are of varying lengths.
So my macro so far looks like this. Two main questions:
DEFINE !varnum(). !DO !I = 1 !TO 21.
loop #I = 1 to THIS NUMBER VARIES DEPENDING ON VECTOR. loop if (vars!I(#I)=1). compute vars!I(#I+1) = 0. end loop if (#I = 6). end loop. exe.
!DOEND.
!ENDDEFINE.
Any help is as always mucho appreciated!
Thanks Matt
Matthew Pirritano, Ph.D. Research Analyst IV Medical Services Initiative (MSI) Orange County Health Care Agency (714) 568-5648
New Windows 7: Simplify what you do everyday. Find the right PC for you. |
|
In reply to this post by mpirritano
At 02:28 PM 4/1/2010, Pirritano, Matthew wrote:
Im brand new to macros. Im trying to translate some sas into spss.Nope. (Sigh.) That's one of a number of useful SAS features that SPSS chose not to include, when otherwise bringing the transformation language up closer to the capabilities of SAS's DATA step. I don't know if you can even do this going into Python; I don't know whether Python has cognizance of the vectors in the dataset it's looking at. :-( Rather than debugging the macro, I'd change the approach. 'Idiomatic' SPSS uses macros far less than most SAS programmers do. Partly, that's because SAS's macro facility is, well, better; and partly, it's because SPSS has features that can often sidestep the need for a macro. One of those is DO REPEAT, a macro-like facility for stepping through parallel lists. Like the following, assuming that your requirement is that, if the first element of the vector is 1, all other elements should be made 0. (Note use of "#Ix" as the loop index variable. That's an SPSS 'scratch variable'; among other things, it isn't included in the output dataset.) [TestData] RecNum V1 V2 V3 W1 W2 W3 W4 X1 X2 X3 X4 X5 001 13 12 14 14 12 11 14 15 13 13 14 13 002 14 12 12 1 13 13 14 12 14 12 15 11 003 12 13 15 13 13 12 12 11 12 13 14 13 004 12 13 13 1 11 14 15 13 15 14 13 14 005 1 13 13 12 14 13 12 1 13 12 13 14 006 13 13 12 1 13 14 13 15 15 14 13 12 007 13 14 13 1 14 12 14 14 14 11 13 15 008 1 14 15 14 13 13 13 13 15 13 14 12 Number of cases read: 8 Number of cases listed: 8 VECTOR Vect3 = V1 TO V3 /Vect4 = W1 TO W4 /Vect5 = X1 TO X5. DO REPEAT Vectr = Vect3 Vect4 Vect5 /Limit = 3 4 5. * If the first element of a vector is 1, make all other elements 0 . . DO IF Vectr(1) EQ 1. . LOOP #Ix = 2 TO Limit. . COMPUTE Vectr(#Ix) = 0. . END LOOP. . END IF. END REPEAT. LIST. List |-----------------------------|---------------------------| |Output Created |03-APR-2010 16:58:31 | |-----------------------------|---------------------------| [TestData] RecNum V1 V2 V3 W1 W2 W3 W4 X1 X2 X3 X4 X5 001 13 12 14 14 12 11 14 15 13 13 14 13 002 14 12 12 1 0 0 0 12 14 12 15 11 003 12 13 15 13 13 12 12 11 12 13 14 13 004 12 13 13 1 0 0 0 13 15 14 13 14 005 1 0 0 12 14 13 12 1 0 0 0 0 006 13 13 12 1 0 0 0 15 15 14 13 12 007 13 14 13 1 0 0 0 14 14 11 13 15 008 1 0 0 14 13 13 13 13 15 13 14 12 Number of cases read: 8 Number of cases listed: 8 ============================= APPENDIX: Test data, and code ============================= * C:\Documents and Settings\Richard\My Documents . * \Technical\spssx-l\Z 2010ab\ . * 2010-04-01 Pirritano - looping in a macro.SPS . * In response to posting . * Date: Thu, 1 Apr 2010 11:28:17 -0700 . * From: "Pirritano, Matthew" <[hidden email]> . * Subject: looping in a macro . * To: [hidden email] . * "I have 21 vectors. Lets say I have a vector named vars1 . * composed of var1 var2 var3. I want to say if var1 = 1, then . * make var2 and var3 = 0." . * ................................................................. . * ................. Test data ..................... . SET RNG = MT /* 'Mersenne twister' random number generator */ . SET MTINDEX = 2295 /* Boston, MA telephone book */ . INPUT PROGRAM. . NUMERIC RecNum (N3). . NUMERIC V1 TO V3 W1 TO W4 X1 TO X5 (F2). . VECTOR AllData=V1 TO X5. . LOOP RecNum = 1 TO 8. . LOOP #Ix = 1 TO 3+4+5. . COMPUTE AllData(#Ix) = 10+RV.BINOM(5,3/5). . END LOOP. * Special case: all vector-beginnings are 1 . * with probability (a little more than) 1/3. . . DO REPEAT VectBegn = V1 W1 X1. . IF RV.BERNOULLI(1/3) VectBegn = 1. . END REPEAT. . END CASE. . END LOOP. END FILE. END INPUT PROGRAM. DATASET NAME TestData. * ................. Test data ..................... . LIST. VECTOR Vect3 = V1 TO V3 /Vect4 = W1 TO W4 /Vect5 = X1 TO X5. DO REPEAT Vectr = Vect3 Vect4 Vect5 /Limit = 3 4 5. * If the first element of a vector is 1, make all other elements 0 . . DO IF Vectr(1) EQ 1. . LOOP #Ix = 2 TO Limit. . COMPUTE Vectr(#Ix) = 0. . END LOOP. . END IF. END REPEAT. LIST. ===================== To manage your subscription to SPSSX-L, send a message to [hidden email] (not to SPSSX-L), with no body text except the command. To leave the list, send the command SIGNOFF SPSSX-L For a list of commands to manage subscriptions, send the command INFO REFCARD |
|
Richard, I wound up tweaking your syntax a little
because I needed to set any ‘subsequent’ ones to zero. The first
value in a vector was not always one, it could have been anywhere in the
vector. Just wanted all subsequent values set to zero. So here’s what I
got: do repeat vectr = vars1 to vars21 /limit = 6 5 6 6
3 5 4 2 2 4 2 5 6 5 2 6 3 6 6 5 5. loop #I = 1 to limit. do if (vectr(#I) =
1). loop #J = (#I
+1) to limit. compute
vectr(#J) = 0. end loop. end if. end loop. end repeat. exe. Works great! Thanks Matt Matthew Pirritano, Ph.D. Research Analyst IV Medical Services Initiative (MSI) Orange County Health Care Agency (714) 568-5648 From: Richard Ristow
[mailto:[hidden email]] At 02:28 PM 4/1/2010, Pirritano, Matthew wrote: I’m brand new to macros. I’m trying to translate some sas
into spss.
Nope. (Sigh.) That's
one of a number of useful SAS features that SPSS chose not to include, when
otherwise bringing the transformation language up closer to the capabilities of
SAS's DATA step. I don't know if you can even do this going into Python; I
don't know whether Python has cognizance of the vectors in the dataset it's
looking at. :-(
Rather than
debugging the macro, I'd change the approach. 'Idiomatic' SPSS uses macros far
less than most SAS programmers do. Partly, that's because SAS's macro facility
is, well, better; and partly, it's because SPSS has features that can often
sidestep the need for a macro. One of those is DO REPEAT, a macro-like facility
for stepping through parallel lists. Like the following, assuming that your
requirement is that, if the first element of the vector is 1, all other
elements should be made 0. (Note use of "#Ix" as the loop index
variable. That's an SPSS 'scratch variable'; among other things, it isn't
included in the output dataset.) |
|
In reply to this post by Richard Ristow
Comments below. Jon Peck SPSS, an IBM Company [hidden email] 312-651-3435
At 02:28 PM 4/1/2010, Pirritano, Matthew wrote: I’m brand new to macros. I’m trying to translate some sas into spss. I have 21 vectors. Let’s say I have a vector named vars1 composed of var1 var2 var3. I want to say if var1 = 1, then make var2 and var3 = 0. The vectors are of varying lengths. Two main questions :
>>>Vectors in SPSS are transient and not visible to Python code, but it is very easy to define them on the Python side and then use that structure. For example, if you want a set of variables consisting of all variables named var1 ... varn, you can get a VariableDict object in Python like this. import spss, spssaux myvector = spssaux.VariableDict(pattern="var\d+$") Then you can iterate over the variables in this mini-dictionary or just get a list of these variables as myvector.variables. Use the spss.Dataset class to change these values. This has the extra advantage that the variables do not have to be consecutive in the SPSS variable dictionary. Regards, Jon |
|
In reply to this post by mpirritano
At 01:37 PM 4/5/2010, Pirritano, Matthew wrote:
I wound up tweaking your syntax a little because I needed to set any subsequent ones to zero. The first value in a vector was not always one, it could have been anywhere in the vector. Just wanted all subsequent values set to zero. [Below is] what I got. Works great! Great! I'm going to suggest one addition: a BREAK statement, to terminate the outer loop as soon as a 1 is reached and the remaining elements are set to 0. That'll speed things up a little bit. (Change not tested) do repeat vectr = vars1 to vars21 (I've also deleted the ".exe", but I always do that, right?) -Cheers, congratulations, and good luck, Richard ===================== To manage your subscription to SPSSX-L, send a message to [hidden email] (not to SPSSX-L), with no body text except the command. To leave the list, send the command SIGNOFF SPSSX-L For a list of commands to manage subscriptions, send the command INFO REFCARD |
| Free forum by Nabble | Edit this page |
