Systematically renaming variables in SPSS (without Python) - spss

I'm looking for a solution to rename variables in SPSS. I can't use Python because of software restrictions at my workplace.
The goal is to rename variables into "oldname_new".
I tried "do repeat" like this, but it can't be combined with the rename function.
do repeat x= var1 to var100.
rename var (x=concat("x","_new")).
end repeat print.
exe.
Also, I figured that even without the do repeat, the rename command doesn't allow concat and similar commands? Is that correct?
So, is there any solution for this in SPSS?

As you found out you can't use rename within a do repeat loop.
SPSS macro can do this -
define DoNewnames ()
rename vars
!do !v=1 !to 100 !concat("var", !v, " = var", !v, "_new") !doend .
!enddefine.
* now the macro is defined, we can run it.
DoNewnames .
EDIT:
The code above is good for a set of variables with systematic names. In case the names are not systematic, you will need a different macro:
define DoNewnames (varlist=!cmdend)
rename vars
!do !v !in(!varlist) !concat(!v, " = ", !v, "_new") !doend .
!enddefine.
* Now in this case you need to feed the variable list into the macro.
DoNewnames varlist = age sex thisvar thatvar othervar.
If you want to see the syntax generated by the macro (like you did with end repeat print) you can run this before running the macro:
set mprint on.
EDIT 2:
As the OP says - the last macro requires naming all the variables to be renamed, which is a hassle if there are many. So the next code will get them all automatically without naming them individually. The process - as described in #petit_dejeuner's comment - creates a new data set that contains each original variable as an observation, and the original variable name as a value (=meta information about the variables, like a codebook). This way, you can recode the variable name into the renaming syntax.
dataset name orig.
DATASET DECLARE varnames.
OMS /SELECT TABLES /IF COMMANDS=['File Information'] SUBTYPES=['Variable Information']
/DESTINATION FORMAT=SAV OUTFILE='varnames' VIEWER=NO.
display dictionary.
omsend.
dataset activate varnames.
string cmd (a50).
compute cmd=concat("rename vars ", rtrim(var1), " = ", rtrim(var1), "_new .").
* Before creating the rename syntax in the following line, this is your chance to remove variables from the list which you do not wish to rename (using "select if" etc' on VAR1).
write out="my rename syntax.sps" /cmd.
dataset activate orig.
insert file="my rename syntax.sps" .
A couple of notes:
Before writing to (and inserting from) "my rename syntax.sps" you may need to add a writable path in the file name.
This code will rename ALL the variable in the dataset. If you want to avoid some of the variables - you should filter them in the variable list before writing out to "my rename syntax.sps" (see where I point this out in the code).

Related

Invalid '`' error when using local macro

I am following instructions from this link on how to append Stata files via a foreach loop. I think that it's pretty straightforward.
However, when I try to refer to each f in datafiles in my foreach loop, I receive the error:
invalid `
I've set my working directory and the data is in a subfolder called csvfiles. I am trying to call each file f in the csvfiles subfolder using my local macro datafiles and then append each file to an aggregate Stata dataset called data.dta.
I've included the code from my do file below:
clear
local datafiles: dir "csvfiles" files "*.csv"
foreach f of local datafiles {
preserve
insheet using “csvfiles\`f'”, clear
** add syntax here to run on each file**
save temp, replace
restore
append using temp
}
rm temp
save data.dta, replace
The backslash character has meaning to Stata: it will prevent the interpretation of any following character that has a special meaning to Stata, in particular the left single quote character
`
will not be interpreted as indicating a reference to a macro.
But all is not lost: Stata will allow you to use the forward slash character in path names on any operating system, and on Windows will take care of doing what must be done to appease Windows. Replacing your insheet command with
insheet using “csvfiles/`f'”, clear
should solve your problem.
Note that the instructions you linked to do exactly that; some of the code includes backslashes in path names, but where a macro is included, forward slashes are used instead.

Changing values of a lot of variables

I want to change the missing values of a lot of variables into 0.I've written this code(There are a lot more of variables,it's just an example):
RECODE variable1 ($SYSMIS = 0).
EXECUTE.
RECODE variable2 ($SYSMIS = 0).
EXECUTE.
RECODE variable3 ($SYSMIS = 0).
EXECUTE.
Is there a simpler way to do the same?Like a while in programming or something like that
Thanks you very much
Your first step should be to combine all your commands into one - this can be done whatever the order of the variables - just explicitly mention all the variable names in the command (as david mentioned):
RECODE variable1 variable2 variable3 variable4 .... (sysmis=0).
This will save quite a lot of code already.
now, as Jignesh mentioned - for variables that are in consecutive order, you can use to:
RECODE variable1 to variable3 (sysmis=0).
or also an example with two groups of consecutive variables and two additional separate variables:
RECODE variable1 TO variable23 var1 TO var7 AnotheVar3 AnotheVar12 (sysmis=0).
definitely no need for looping commands here.
If the desired target variables are in consecutive order in your active dataset you can use the keyword TO.
For example:
RECODE V1 to V3 (SYSMIS=0).
Note your incorrect use of keyword "SYSMIS" in the RECODE command and the corrected in example code provided.
Else you will have to resort to using DO REPEAT or DEFINE/ENDDEFINE.
In addition to Jignesh's response, If all of the variables are Numeric you can use ALL.
RECODE ALL(SYSMIS=0).
DEFINE !ENDDEFINE would be Overkill, DO REPEAT doesn't buy you anything over explicitly listing the variables in the RECODE command.

Stata local based on other local

I am trying to use local with the value of an earlier use of local. An example: I want to define "final" and I want it to contain "var1 var2". However, I want to define "temp" first, and reuse its contents in the definition of final.
Here is what I tried:
local temp "var2"
local final "var1 " `temp'
Can anyone tell me what I am doing wrong?
An example that works:
// example data
sysuse auto, clear
// what you want
local first weight
local second `first' mpg
// example use of local second
regress price `second'
Edit
To answer your comment:
Yes, your problem are the double quotes. That doesn't mean, however, that using double quotes will automatically get you in trouble. For example, this will work:
// example data
sysuse auto, clear
// what you want
local first "weight"
local second "mpg `first'"
// example use of local second
regress price `second'
Double quotes here are interpreted as string delimiters, and so will be stripped. When local first is (de)referenced in local second "mpg `first'", macro-substitution will insert weight, not "weight". Afterwards, when local second is (de)referenced in regress ..., macro-substitution results in mpg weight, not "mpg weight". So it's all legal syntax.
Your example contains invalid syntax. You delimit the first piece with double quotes and then continue with another piece:
`temp'
That is considered illegal.
Stata doesn't mind if we omit the double quotes in the local statement, which is why my first example works. See [U] 18.3.4 Macros and expressions.
See also http://www.stata.com/statalist/archive/2009-01/msg00282.html and help quotes.

How to implement command-line variables in Xtext

I want my Domain specific language (DSL) to accept command-line arguments as variables like in bash scripts. For example: A user might issue a command runMyDSL myDslFile.dsl -args 10 15 or runMyDSL myDslFile.dsl -nvargs arg1=10 arg2=15. I would like to capture these values into variables $1, $2 for first command or $arg1, $arg2 for second command. These variables can then be treated as any other read-only variables in my DSL:
val someVariable = $1
Since I am new to xtext/parser field, I am looking for best practices people follow for dealing with this situation. For simplicity, let's assume, I am only working on simplified DSL that does addition (based on Expression Language described in http://blog.efftinge.de/2010/08/parsing-expressions-with-xtext.html):
Expression : Variable '+' Variable;
Variable: ('val' ID '=' INT) | CommandLineVariable;
CommandLineVariable: ??;
My first idea for that would be the following:
1.) parse the DSL file and get access to the AST, store the refence in any locally definded variable of the corresponding EClass.
2.) Use the 'MyDslFactory' class to create a new 'Variable' instance, set a value, given by the command line and put it somewhere into the AST.
To do that you should define attribute names in you 'Variable' Parser Rule:
Variable: 'val' name=ID '=' value=INT;
'Variable' creation would look like this (more or less):
Variable newVar = MyDslFactory.eINSTANCE.createVariable();
newVar.setName(args[2].split("=")[0]);
newVar.setValue(new Integer(args[2].split("=")[1]));
Then you put it into the AST and with the modified AST you could either create a temporary DSL file which is then processed as before or you process the AST directly.

TeX edef macro blues

I spent some time trying to write a 'helper' macro to test a parameter for a new value, else use the existing value -- default values exist for all parameter positions.
I wanted to be able to write:
\foo{left}{nil}{}{20pt}
so that the second parameter would used its current value but the third value would be the value empty string. I wanted to use the notation:
\edef\pA{\isnil{#1}{\pA){#1}} % one for each parameter
I defined \isnil like so:
\def\nil{nil}
\def\isnil#1#2#3{%
\edef\nilTest{#1}%
\ifx\nilTest\nil#2\else#3\fi
}
but when I tried to run it, TeX complained that \nilTest is an undefined control sequence.
That is true of course, but I want \pA to hold a value, not a recipe for a value, so it must be an \edef which means that all the macro test will be expanded but while will the \edef not protect the \nilTest -- is this a place to use \noexpand -- that did not seem to work for me.
EDIT: no digits in \cs names (yeah, I knew that.)
Why doesn't your solution work? \edef\pA{\isnil{#1}{\pA){#1}} expands \isnil and gets \edef\nilTest{.... Now \edef is not expandable and falls into a sequence of \pA as the first element. An attempt to expand the next macro \nilTest fails.
Use \setpar from the following code to change your parameter.
\def\nil{nil}
\def\setpar#1#2{%
\edef\nilTest{#2}%
\ifx\nilTest\nil\else\let#1\nilTest\fi}
\def\first{old first}
\def\second{old second}
\setpar \first{nil}
\setpar \second{new}
first = ``\first'', second = ``\second''
P.S. Do not use digits in your macro.

Resources