How to write a python function inside SPSS that creates new variables and appends them to the SPSS dataset?

Viewed 58

I have recently started writing small Python program blocks in SPSS. In my current dataset I coalesce two variables like this:

BEGIN PROGRAM PYTHON3.
import spss, spssdata
data = spssdata.Spssdata(indexes = ('var1', 'var2'), accessType = 'w')
data.append(spssdata.vdef("newvar"))
data.commitdict()
for row in data:
    if row.var1== None:
        data.setvalue("newvar", row.var2)
    else:
        data.setvalue("newvar", row.var1)        
data.CClose()
END PROGRAM.

The above program works perfectly well and now I would like to create a function as I need to coalesce many more variables. The best solution I came up with so far is this one:

BEGIN PROGRAM PYTHON3.
import spss, spssdata
def coalesce(var1, var2, newvar):
    data = spssdata.Spssdata(indexes = (var1, var2), accessType = 'w')
    data.append(spssdata.vdef(newvar))
    data.commitdict()
    for row in data:
        if row.var1 == None:
            data.setvalue("newvar", row.var1)
        else:
            data.setvalue("newvar", row.var2)        
    data.CClose()
END PROGRAM.    

However, I get the following error message when trying to run it on my variables:

BEGIN PROGRAM PYTHON3.
coalesce('Statements1', 'Statements2', 'Statements12')
END PROGRAM.

Warning: An open Cursor was detected while exiting a program block. The Cursor has been closed.
Traceback (most recent call last):
  File "<string>", line 2, in <module>
  File "<string>", line 8, in coalesce
AttributeError: 'namedTuple' object has no attribute 'var1'

I suppose that the problem is that I am passing the tuple name rather than the tuple in line 8 but I don't know how to fix that. Already tried different solutions, e.g., tried to pass the variable without quotes in the function but this did not work either. Also, tried to do something like row[var1] in line 8 but it seems that spssdata is not able to work with that.

Anyone who can help me with this problem? Thank you!

1 Answers

In the meantime I came up with a solution myself. Maybe not the most elegant one but it works fine. In the "set.value" part in which the error ocurred I am now taking advantage of the fact that the variable row is a tuple, which can also be accessed by index. So, row[0] refers to the values of var1 and row[1] the values of var2.

Furthermore, I am using SPSS to rename the new variable after creating it.

BEGIN PROGRAM PYTHON3.
import spss, spssdata, spssaux
def coalesce(var1, var2, nameAggregate):
    #get Variable dictionary info in order to get variable label
    sDict = spssaux.VariableDict(caseless = True) 
    var1Label = sDict[var1].VariableLabel
    #create data cursor
    data = spssdata.Spssdata(indexes = (var1, var2), accessType = 'w')
    data.append(spssdata.vdef("newvar"))
    data.commitdict()
    for row in data:
        if row[0] == None:
            data.setvalue("newvar", row[1])
        else:
            data.setvalue("newvar", row[0])        
    data.CClose()
    #copy label and add "COALESCED" as a prefix
    spss.Submit(r"""
    APPLY DICTIONARY FROM * 
    /source variables = %(var1)s 
    /target variables = newvar      
    /VARINFO MISSING VALLABELS=REPLACE.
    VARIABLE LABELS newvar "COALESCED: %(var1)s & %(var2)s %(var1Label)s".
    RENAME VARIABLES (newvar = %(nameAggregate)s).
    """%locals())
END PROGRAM.

Example use:

BEGIN PROGRAM PYTHON3.
coalesce('Statement1', 'StatementsNot1', 'AggregateStatement1')
END PROGRAM.

I further recommend this resource for python programming inside SPSS https://www.spsstools.net/en/documents/76/SPSS-Programming-and-Data-Management-3rd-Edition.pdf

Related