Code Examples

I have used a variety of coding languages in my research, both for organizing and analyzing data, as well as for designing materials for studies. With the exception of my experience with MatLab—which I first learned from sitting in on two lectures for a programming course—I am almost entirely self-taught. I spent a few hours of my free time each week during my MA and PhD learning how to write and apply code for a variety of purposes. Below are several examples of code that I have written and used in my own work.

SQL

  -- Typically I do these pulls for several hundred cases minimum.
  -- This grabs all the major variables we needed and exports them in one complete table.
  -- Database and table names have been changed for security reasons.
  
  --DROP TABLE #SAMPLE
  
  CREATE TABLE #SAMPLE (
  	MRN NVARCHAR(7),
  	VISIT NVARCHAR(8),
  	SURG_DT DATE	
  )
  
  INSERT INTO #SAMPLE
  VALUES ('/* 7 digit MRN */','/* 8 digit visit number */','/* yyyy-mm-dd */'),
  	('/* 7 digit MRN */','/* 8 digit visit number */','/* yyyy-mm-dd */'),
  	('/* 7 digit MRN */','/* 8 digit visit number */','/* yyyy-mm-dd */'),
  	('/* 7 digit MRN */','/* 8 digit visit number */','/* yyyy-mm-dd */'),
  	('/* 7 digit MRN */','/* 8 digit visit number */','/* yyyy-mm-dd */'),
  	('/* 7 digit MRN */','/* 8 digit visit number */','/* yyyy-mm-dd */'),
  	('/* 7 digit MRN */','/* 8 digit visit number */','/* yyyy-mm-dd */'),
  	('/* 7 digit MRN */','/* 8 digit visit number */','/* yyyy-mm-dd */'),
  	('/* 7 digit MRN */','/* 8 digit visit number */','/* yyyy-mm-dd */')
  
  
  ALTER TABLE #SAMPLE
  ADD ASA_CLASS NVARCHAR(40) --DB1.SURGICAL_CASE
  	,PT_ZIP VARCHAR(50) --DB2.PATDEMO
  	,PT_CITY VARCHAR(50) --DB2.PATDEMO
  	,PT_STATE VARCHAR(30) --DB2.PATDEMO
  	,DATE_BIRTH DATE --DB2.PATDEMO
  	,SEX VARCHAR(1) --DB2.PATDEMO
  	,NAME_LAST VARCHAR(200) --DB3.PATIENT
  	,NAME_FIRST VARCHAR(200) --DB3.PATIENT
  	,EBL_ML VARCHAR(255)
  	,PSYCH_HX NVARCHAR(1)
  	,DM NVARCHAR(1)
  	,ALCOHOL NVARCHAR(255)
  	,ALCOHOL_TEXT NVARCHAR(MAX)
  	,TOBACCO NVARCHAR(255)
  	,TOBACCO_TEXT NVARCHAR(MAX)
  	,SUB_ABUSE NVARCHAR(255)
  	,SUB_ABUSE_TEXT NVARCHAR(MAX)
  	,BMI NVARCHAR(255)
  	,RACE VARCHAR(40)
  	,ETHNICITY VARCHAR(40)
  
  
  
  WITH EBL_AGG AS
  (
  SELECT DISTINCT a.MRN
  	,a.VISIT
  	--,SUM(CAST(RESULT_VAL AS INT)) AS EBL_ML
  	,DISP1
  	,DISP2
  	,DISP3
  	,DISP4
  	,RESULT_VAL
  	,EVENT_END_DT_TM
  FROM #SAMPLE a
  	,DB3.NURSING_DOC b
  WHERE a.VISIT = b.VISIT
  	AND DISP4 LIKE 'EBL in OR (mL)'
  	AND CAST(EVENT_END_DT_TM AS DATE) = SURG_DT
  ),
  EBL AS 
  (
  SELECT DISTINCT MRN
  	,VISIT
  	,SUM(CAST(RESULT_VAL AS INT)) AS EBL_ML
  FROM EBL_AGG
  GROUP BY MRN,VISIT
  ),
  DX AS 
  (
  SELECT DISTINCT a.MRN
  	,a.VISIT
  	,SURG_DT
  	,MAX((CASE
  		WHEN DX_CODE BETWEEN 'F01' AND 'F09.999' THEN '1'
  		WHEN DX_CODE BETWEEN 'F20' AND 'F99' THEN '1'
  		ELSE '0'
  		END
  	)) AS PSYCH_HX
  FROM #SAMPLE a
  	,DB3.DIAGNOSIS b
  WHERE LEN(DX_CODE) < '8'
  	AND LEN(DX_CODE) > '2'
  	AND DX_DT_TM <= SURG_DT
  	AND a.MRN = b.MRN
  GROUP BY a.MRN,a.VISIT,SURG_DT
  ),
  DIABETUS AS 
  (
  SELECT DISTINCT a.MRN
  	,a.VISIT
  	,SURG_DT
  	,MAX((CASE
  		WHEN DX_CODE BETWEEN 'E08' AND 'E13.999' THEN '1'
  		ELSE '0'
  		END
  	)) AS DM
  FROM #SAMPLE a
  	,DB3.DIAGNOSIS b
  WHERE LEN(DX_CODE) < '8'
  	AND LEN(DX_CODE) > '2'
  	AND DX_DT_TM <= SURG_DT
  	AND a.MRN = b.MRN
  GROUP BY a.MRN,a.VISIT,SURG_DT
  ),
  AGG_HIST AS
  (
  SELECT DISTINCT b.MRN
  	,CATEGORY
  	,ELEMENT
  	--,RESPONSE
  	,MAX(LAST_UPDATED) AS UPDATED
  FROM DB3.SOCIAL_HISTORY a
  	,#SAMPLE b
  WHERE a.MRN = b.MRN 
  	AND CATEGORY IN ('Alcohol', 'Tobacco', 'Substance Abuse')
  	AND ELEMENT = 'Use:'
  	AND LAST_UPDATED <= SURG_DT
  GROUP BY b.MRN
  	,CATEGORY
  	,ELEMENT
  ),
  CURRENT_HIST AS
  (
  SELECT a.MRN
  	,a.CATEGORY
  	,b.ELEMENT
  	,UPDATED
  	,RESPONSE
  	,DETAILS
  FROM AGG_HIST a
  	,DB3.SOCIAL_HISTORY b
  WHERE UPDATED = LAST_UPDATED
  	AND a.MRN = b.MRN
  	AND a.CATEGORY = b.CATEGORY
  	AND b.ELEMENT = 'Use:'
  --ORDER BY a.MRN, a.CATEGORY, b.ELEMENT
  ),
  --
  --
  --
  --
  --CHANGE CODE BELOW BASED ON WHAT RESPONSES THERE ARE FOR THE CATEGORIES
  --
  --
  --
  --
  SUB_HIST AS
  (
  SELECT a.MRN
  	,VISIT
  	,(CASE
  		WHEN (CATEGORY = 'Alcohol'
  			AND RESPONSE IN ('Current', 'Past', 'Never')
  			) THEN RESPONSE
  		ELSE ''
  		END
  	) AS ALCOHOL
  	,(CASE
  		WHEN (CATEGORY = 'Alcohol'
  			AND RESPONSE IN ('Current', 'Past', 'Never')
  			) THEN DETAILS
  		ELSE ''
  		END
  	) AS ALCOHOL_TEXT
  	,(CASE
  		WHEN (CATEGORY = 'Tobacco'
  			AND RESPONSE IN ('Current', 'Current every day smoker', 'Current some day smoker', 'Former smoker', 'Never smoker', 'Past')
  			) THEN RESPONSE
  		ELSE ''
  		END
  	) AS TOBACCO
  	,(CASE
  		WHEN (CATEGORY = 'Tobacco'
  			AND RESPONSE IN ('Current', 'Current every day smoker', 'Current some day smoker', 'Former smoker', 'Never smoker', 'Past')
  			) THEN DETAILS
  		ELSE ''
  		END
  	) AS TOBACCO_TEXT
  	,(CASE
  		WHEN (CATEGORY = 'Substance Abuse'
  			AND RESPONSE IN ('Current', 'Past', 'Never')
  			) THEN RESPONSE
  		ELSE ''
  		END
  	) AS SUB_ABUSE
  	,(CASE
  		WHEN (CATEGORY = 'Substance Abuse'
  			AND RESPONSE IN ('Current', 'Past', 'Never')
  			) THEN DETAILS
  		ELSE ''
  		END
  	) AS SUB_ABUSE_TEXT
  --INTO SUB_HIST
  FROM #SAMPLE a
  	,CURRENT_HIST b
  WHERE a.MRN = b.MRN
  	AND UPDATED <= SURG_DT
  ),
  BMI AS
  (
  SELECT DISTINCT a.MRN
  	,b.VISIT AS SURGERY
  	,a.VISIT AS PRE_VISIT
  	,RESULT_VAL
  --INTO #BMI
  FROM DB3.NURSING_DOC a, #SAMPLE b
  WHERE a.MRN = b.MRN
  	AND a.VISIT <= b.VISIT
  	AND EVENT_TITLE_TEXT = 'Body Mass Index'
  	AND RESULT_VAL  '0.00'
  ),
  BMI_VISIT AS
  (
  SELECT MRN
  	,SURGERY
  	,MAX(PRE_VISIT) AS PRE_VISIT
  --INTO #BMI_VISIT
  FROM BMI
  WHERE PRE_VISIT <= SURGERY
  GROUP BY SURGERY,MRN
  ),
  BMI_VAL AS 
  (
  SELECT a.MRN
  	,a.SURGERY AS VISIT
  	,RESULT_VAL
  --INTO #BMI_VAL
  FROM BMI_VISIT a, BMI b
  WHERE a.MRN = b.MRN
  	AND a.SURGERY = b.SURGERY
  	AND a.PRE_VISIT = b.PRE_VISIT
  )
  UPDATE #SAMPLE
  SET #SAMPLE.ASA_CLASS = b.ASA_CLASS
  	,#SAMPLE.PT_ZIP = c.PT_ZIP
  	,#SAMPLE.PT_CITY = c.PT_CITY
  	,#SAMPLE.PT_STATE = c.PT_STATE
  	,#SAMPLE.DATE_BIRTH = c.DATE_BIRTH
  	,#SAMPLE.SEX = c.SEX
  	,#SAMPLE.NAME_LAST = d.NAME_LAST
  	,#SAMPLE.NAME_FIRST = d.NAME_FIRST
  	,#SAMPLE.RACE = d.RACE
  	,#SAMPLE.ETHNICITY = d.ETHNICITY
  	,#SAMPLE.EBL_ML = e.EBL_ML
  	,#SAMPLE.PSYCH_HX = f.PSYCH_HX
  	,#SAMPLE.DM = g.DM
  	,#SAMPLE.ALCOHOL = h.ALCOHOL
  	,#SAMPLE.ALCOHOL_TEXT = h.ALCOHOL_TEXT
  	,#SAMPLE.TOBACCO = h.TOBACCO
  	,#SAMPLE.TOBACCO_TEXT = h.TOBACCO_TEXT
  	,#SAMPLE.SUB_ABUSE = h.SUB_ABUSE
  	,#SAMPLE.SUB_ABUSE_TEXT = h.SUB_ABUSE_TEXT
  	,#SAMPLE.BMI = i.RESULT_VAL
  FROM #SAMPLE a
  	LEFT JOIN DB1.SURGICAL_CASE b ON a.MRN = b.MRN AND a.VISIT = b.VISIT
  	LEFT JOIN DB2.PATDEMO c ON a.MRN = c.MRN
  	LEFT JOIN DB3.PATIENT d ON a.MRN = d.MRN
  	LEFT JOIN EBL e ON (a.MRN = e.MRN AND a.VISIT = e.VISIT)
  	LEFT JOIN DX f ON (a.MRN = f.MRN AND a.VISIT = f.VISIT AND a.SURG_DT = f.SURG_DT)
  	LEFT JOIN DIABETUS g ON (a.MRN = g.MRN AND a.VISIT = g.VISIT AND a.SURG_DT = g.SURG_DT)
  	LEFT JOIN SUB_HIST h ON (a.MRN = h.MRN AND a.VISIT = h.VISIT)
  	LEFT JOIN BMI_VAL i ON (a.MRN = i.MRN AND a.VISIT = i.VISIT)

R

I use R for nearly all of my data analysis needs. Below is an example of the annotated syntax I made for a colleague so that she could see how to generate the same results in R as in MPlus for modelling indirect effects in a structural model with two latent intermediate variables and a latent outcome variable.

 # You will need to install the lavaan and semPlot packages.  Install using 'install.packages()'.
 ## NOTE: You only need to install packages once! After that, you only need to reference the library.
  install.packages("lavaan")
  install.packages("semPlot")
 
 # I tried to set this up so that it could be reused without much modification.  The only bits that will
 # need changing should be the name of the data file and the model specification.  As far as I can tell,
 # everything else is pretty generic. 
 
 # To format the file for lavaan, I did the same things I would have for Mplus, but then I saved it as a CSV
 # file instead of a DAT file.  Make sure the variable names are saved to the first line of the CSV.
 # As far as I can tell, there's no limit on how long the file path can be, so you can save the file wherever
 # you want (and can easily get the file path).  I usually save it to my desktop so that I can reuse the code 
 # for setting the file directory.  Here's an example of how to set your working directory:
  getwd() # This will tell you what your current directory is
 ## My default directory is '[1] "C:/Users/droletca/Documents"'
 ## I used the directory from the output, which said it was set to my Documents folder, and modified it so that
 ## it was set to my Desktop ('C:/Users/droletca/Documents' changed to 'C:/Users/droletca/Desktop').
 ## Then I set the working directory to the Desktop using the syntax below.
  setwd("C:/Users/droletca/Desktop")
 
 # After you've set your working directory to the location the has your data file, you can use the syntax
 # below to import the data into R.  Just change "Dance Study_Dancer (FULL)_MPLUS(03.14.2019).csv" to
 # the name of your data file.
  myData <- read.csv("Dance Study_Dancer (FULL)_MPLUS(03.14.2019).csv")
 
 # To recode missing data values if they were numerically coded
 ## To avoid having missing data included in the analysis, it is easiest be recoded them as 'NA'.
 ## To recode a specific variable, use 'myData$' followed by the variable name. 
  myData[myData == -999] <- NA
 
 # Specify the model.
 ## The layout is super similar to Mplus (there is even syntax for converting Mplus syntax to lavaan,
 ## but it doesn't always do a very good job).  
 ## - Name paths for mediation or moderation tests by putting the path label in front of the predictor with a '*'
 ##   (e.g., 'b1*SAT').  Use the same method for specifying loadings (e.g., '1*SAT').
 ## - Mplus 'by' is '=~' in lavaan.
 ## - Mplus 'on' is '~' in lavaan.
 ## - Mplus 'with' is '~~' in lavaan.
 ## - If there are multiple variables on the right side of '=~', '~', or '~~', they must be connected by '+'.
 ## - Test indirect paths, total effects, and simple slopes by defining parameters (e.g., 'indirect1 := a1 * b1')
 ## As long as the variable names are printed in the top row of your data file, they will be recognized.
 ## NOTE: R syntax is case sensitive! The model won't work if the variable names are not exactly the same
 ## as the names in your data file. Also, make sure you include the last apostrophe when running this syntax!
  library(lavaan)
  Dance.model <- '
      VESTED =~ IMPRTNT + ENJOY
      SAT =~ ASAT + RLSAT + COMSAT
      FRU =~ AFR + RLFR + COMFR
      COMFR ~~ COMSAT
      SOP ~~ SPP
      SAT ~~ FRU
      SAT ~ SOP + a1*SPP
      FRU ~ SOP + SPP
      VESTED ~ b1*SAT + FRU
      indirect1 := a1 * b1
  '
 
 # NOTE: For most models, the syntax below can be run without any changes.
 
 # Calculate model estimates/coefficients
 ## The syntax below gives estimates that are almost identical to what you would get in Mplus. The only 
 ## difference I noted is that the test of the indirect effect is a tad more conservative.
 ## For the standardize coefficients, use the Std.all column.
 ## NOTE: The bootstrapping procedures in R don't appear to be as efficient as the ones in Mplus, so expect 
 ## to be waiting approximately 1s for every 10 bootstraps (so 5000 bootstraps would take around 8.33 minutes
 ## or more). The bootstrapping can run in the background while you do other things, but it might delay it a bit.
  fit <- lavaan(Dance.model, data= myData, auto.var=TRUE, 
      int.ov.free = TRUE,
      auto.fix.first=TRUE, auto.cov.lv.x=TRUE,
      se = "bootstrap",bootstrap = 1000,
      missing="fiml")
 
 # Show model summary and statistics
  summary(fit, fit.measures=TRUE, standardize=TRUE, rsquare=TRUE,
      estimates = TRUE, ci = TRUE)
 
 # Path diagram
 ## I added a bunch of stuff to make the diagram look nice, but you could also use 'semPaths(fit)' for 
 ## just a basic path model with no loadings.
  library(semPlot)
  semPaths(fit,"std", "est", style="lisrel", layout="tree2", 
      covAtResiduals=TRUE, residuals=TRUE,
      shapeLat="ellipse", shapeMan="rectangle", nCharNodes=4, 
      color = list(lat = rgb(255, 253, 71, maxColorValue = 255), # Block to remove color
      man = rgb(155, 253, 175, maxColorValue = 255)), # Block to remove color
      mar = c(5, 5, 5, 5), fade=FALSE, weighted=FALSE, 
      edge.color="black", edge.label.cex=0.7, label.norm="OOO", 
      label.prop=0.7, intercepts = FALSE, thresholds = FALSE, 
      rotation = 1,)

Excel Macros

For a study I conducted with Hafer, Davis, and Segalowitz (2019), I had to find and organize the cells for reaction times to specific lines in each of 120 stories. The initial data came from E-Prime and I wrote an excel macro to organize and label the cells we needed for analysis out of the millions of other cells in the dataset that were not needed.

 Sub fullMacro()
     'Before running this macro, check to make sure the highest row value matches the total number of
     'rows in the file (current highest row value is 13911).
     'Also check that the sheet name in the macro matches the sheet name in the file (participants 1-10). 
     '
 
     'This part edits the file so that it is compatible with the file for which the original code was written.
     Sheets("participants 1-10").Select
     Sheets("participants 1-10").Name = "exported merged file"
     Rows("1:1").Select
     Selection.Delete Shift:=xlUp
     Columns("F:F").Select
     Selection.Insert Shift:=xlToRight
     Range("F1").Select
     ActiveCell.FormulaR1C1 = "Delay"
     Range("F2").Select
     ActiveCell.FormulaR1C1 = "150"
     Range("F2").Select
     Selection.Copy
     Range("F3").Select
     ActiveWindow.ScrollRow = 13888
     Range("F3:F13911").Select
     ActiveSheet.Paste
 
     'This part just copies the text from each story line so I can make sure nothing gets shifted up or down.
     Columns("D:D").Select
     Application.CutCopyMode = False
     Selection.Insert Shift:=xlToRight
     Columns("YP:YP").Select
     Selection.Copy
     Columns("D:D").Select
     ActiveSheet.Paste
 
     'This next part collapses the empty cells.
     Range("AE1:YP13911").SpecialCells(xlCellTypeBlanks).Delete Shift:=xlToLeft
 
     'Next, it deletes all the rows for practice trials.
     Columns("W:W").Select
     Selection.AutoFilter
     ActiveSheet.Range("$W$1:$W$13911").AutoFilter Field:=1, Criteria1:= _
         "PracticeProc"
     Range("A2:AV13911").SpecialCells(xlCellTypeVisible).Delete Shift:=xlShiftUp
     Columns("W:W").Select
     Selection.AutoFilter
 
     'One of the columns was really wide, so I adjusted the size.
     Columns("BC:BC").EntireColumn.AutoFit
     Columns("AL:AL").Select
 
     'This next part gets rid of some of the information we don’t need (e.g., onset delay). For whatever reason, the 
     'columns for block 3 don’t align with other blocks (onset delay and onset time columns are missing).
     Selection.AutoFilter
     ActiveSheet.Range("$AL$1:$AL$13911").AutoFilter Field:=1, Criteria1:=Array( _
         "1", "14", "15", "16", "17", "18", "19", "20", "21", "22", "23", "24", "25", "26", "27", "28", _
         "29", "30", "31", "32", "Block1", "Block10", "Block11", "Block12", "Block13", "Block14", _
         "Block15", "Block16", "Block17", "Block18", "Block19", "Block2", "Block20", "Block4", _
         "Block5", "Block6", "Block7", "Block8", "Block9", "="), Operator:=xlFilterValues
     Range("AX1:BA13911").Select
     Range("AX1:BA13911").SpecialCells(xlCellTypeVisible).ClearContents
     Selection.AutoFilter
     Range("AX2:BD13911").SpecialCells(xlCellTypeBlanks).Delete Shift:=xlToLeft
     Range("AX1:YP1").ClearContents
 
     'The next part deletes the rows containing responses to the questions.
     Columns("AJ:AJ").Select
     Selection.AutoFilter
     ActiveSheet.Range("$AJ$1:$AJ$13911").AutoFilter Field:=1, Criteria1:=Array( _
         "a", "b", "c", "d", "e", "="), Operator:=xlFilterValues
     Range("A2:AZ13911").SpecialCells(xlCellTypeVisible).Delete Shift:=xlShiftUp
     Selection.AutoFilter
     Columns("AI:AI").Select
     Selection.AutoFilter
     ActiveSheet.Range("$AI$1:$AI$13911").AutoFilter Field:=1, Criteria1:=Array( _
         "Q12", "="), Operator:=xlFilterValues
     Range("A2:AZ13911").SpecialCells(xlCellTypeVisible).Delete Shift:=xlShiftUp
     Selection.AutoFilter
     Columns("AQ:AW").Select
 
     'Next, it deletes any remaining rows that we don’t need (e.g., info about the version of e-prime).
     Range("AW1").Activate
     Selection.Delete Shift:=xlToLeft
     Columns("AP:AP").Select
     Selection.Delete Shift:=xlToLeft
     Columns("AJ:AK").Select
     Selection.Delete Shift:=xlToLeft
     Columns("AE:AH").Select
     Selection.Delete Shift:=xlToLeft
     Columns("Y:AC").Select
     Range("AC1").Activate
     Selection.Delete Shift:=xlToLeft
     Columns("W:X").Select
     Range("X1").Activate
     Selection.Delete Shift:=xlToLeft
     Columns("S:V").Select
     Range("V1").Activate
     Selection.Delete Shift:=xlToLeft
     Columns("A:A").Select
     Selection.Delete Shift:=xlToLeft
     Columns("D:Q").Select
     Selection.Delete Shift:=xlToLeft
     Range("A2").Select
 
     'Next, it renames each of the columns.
     Range("C1").Select
     ActiveCell.FormulaR1C1 = "StoryText"
     Range("D1").Select
     ActiveCell.FormulaR1C1 = "Set"
     Range("E1").Select
     ActiveCell.FormulaR1C1 = "StoryNum"
     Range("F1").Select
     ActiveCell.FormulaR1C1 = "Block"
     Range("H1").Select
     ActiveCell.FormulaR1C1 = "FullStory"
     Range("I1").Select
     ActiveCell.FormulaR1C1 = "LineNum"
     Range("J1").Select
     ActiveCell.FormulaR1C1 = "RT"
     Range("K1").Select
     ActiveCell.FormulaR1C1 = "RTTime"
     Range("L1").Select
     ActiveCell.FormulaR1C1 = "StoryText2"
     Columns("G:G").Select
     Selection.Delete Shift:=xlToLeft
     Range("A2").Select
 
     'This next part deletes the lines containing ‘x’.
     Columns("K:K").Select
     Selection.AutoFilter
     ActiveSheet.Range("$K$1:$K$13911").AutoFilter Field:=1, Criteria1:="+"
     Range("A2:K13911").SpecialCells(xlCellTypeVisible).Delete Shift:=xlShiftUp
     Selection.AutoFilter
 
     'This next part isolates the lines for the outcomes, copies them to a new sheet, and deletes the first sheet.
     Columns("K:K").Select
     Selection.AutoFilter
     ActiveSheet.Range("$K$1:$K$13911").AutoFilter Field:=1, Criteria1:=Array( _
         "a divorce.", "a flat tire.", "a great job.", "a pay cut.", "a present.", _
         "a relaxing vacation.", "a traffic jam.", "break up.", "contracted mono.", "couldn't sleep.", _
         "coworker he disliked.", "coworker she disliked.", "day off work.", "developed an allergy.", "flight was cancelled.", _
         "food poisoning.", "found $20.", "free baseball tickets.", "free coffee.", "free iPad.", _
         "got lost.", "had been promoted.", "he fell.", "he won.", "her favourite restaurant.", _
         "his favourite restaurant.", "it was missing.", "locked out.", "nice weather.", "on a date.", _
         "on sale.", "perfect parking spot.", "power outage.", "radiator overheated.", "receive $500.", _
         "she fell.", "spilled her coffee.", "sprained ankle.", "stayed dry.", "was complimented.", _
         "was complimented.", "was lost.", "was upgraded.", "were lost.", "="), Operator:=xlFilterValues
     Range("A1:K13911").SpecialCells(xlCellTypeVisible).Copy
     Sheets.Add Type:=xlWorksheet
     ActiveSheet.Name = "outcomesOnly"
     Sheets("outcomesOnly").Select
     ActiveSheet.Paste
     Sheets("exported merged file").Select
     Columns("K:K").Select
     Selection.AutoFilter
     Sheets("exported merged file").Select
     ActiveWindow.SelectedSheets.Delete
     Sheets("outcomesOnly").Select
 End Sub

MatLab

My first introduction to programming was through MatLab. This program helped me to understand syntax structure for a variety of coding languages. The example below was used in conjunction with the Excel macro from the previous section. Once the necessary cells were organized into a csv file, I used MatLab to further arrange and label the data for analysis in SPSS.

 %% ADD LABELS FUNCTION %%
   
 % All you need to do to use this script is answer the two questions it asks
 % at the beginning. 
  
 % NOTE #1: You must have the file containing the data saved to the current
 % folder in order to import the file.
  
 % NOTE #2: Make sure you know the full name of the file, including the file
 % extension (e.g., exported_data.xlsx)
  
 % NOTE #3: Finally, make sure you know the name of the sheet within the
 % excel file that contains the data.
  
 % The file will be saved as 'FinalData.csv' in the current folder.
  
 function addLabels()
     input('Make sure the file is saved to the workspace, then hit "enter"');
     fid = input('What is the name of the file you want to open? ', 's');
     sheet = input('What sheet contains the data? ', 's');
     [~, ~, outcomes] = xlsread(fid, sheet);
     outcomes = outcomes(2:end,:);
     outcomes(cellfun(@(x) ~isempty(x) && isnumeric(x) && isnan(x),outcomes)) = {''};
     [totalrows,totalcolumns]=size(outcomes);
     row = 1;
     while row <= totalrows;
         story = outcomes{row, 5};
         if strcmp(outcomes(row,6),'Block1');
             if story == 1;
                 outcomes(row,12) = {36};
                 outcomes(row,13) = {'3d'};
                 outcomes(row,14) = {'Control'};
             elseif story == 2;
                 outcomes(row,12) = {79};
                 outcomes(row,13) = {'11c'};
                 outcomes(row,14) = {'Deserved'};
             elseif story == 3;
                 outcomes(row,12) = {2};
                 outcomes(row,13) = {'1a'};
                 outcomes(row,14) = {'Undeserved'};
             elseif story == 4;
                 outcomes(row,12) = {73};
                 outcomes(row,13) = {'11a'};
                 outcomes(row,14) = {'Deserved'};
             elseif story == 5;
                 outcomes(row,12) = {109};           
                 outcomes(row,13) = {'15a'};
                 outcomes(row,14) = {'Deserved'};
             elseif story == 6;
                 outcomes(row,12) = {25} ;   
                 outcomes(row,13) = {'3a'};
                 outcomes(row,14) = {'Deserved'};
             end
         elseif strcmp(outcomes(row,6),'Block2');
             if story == 1;
                 outcomes(row,12) = {100};       
                 outcomes(row,13) = {'14b'};
                 outcomes(row,14) = {'Deserved'};
             elseif story == 2;
                 outcomes(row,12) = {28} ;   
                 outcomes(row,13) = {'3b'};
                 outcomes(row,14) = {'Deserved'};
             elseif story == 3;
                 outcomes(row,12) = {98} ;   
                 outcomes(row,13) = {'14a'};
                 outcomes(row,14) = {'Undeserved'};
             elseif story == 4;
                 outcomes(row,12) = {24} ;       
                 outcomes(row,13) = {'2d'};
                 outcomes(row,14) = {'Control'};
             elseif story == 5;
                 outcomes(row,12) = {68} ;       
                 outcomes(row,13) = {'10c'};
                 outcomes(row,14) = {'Undeserved'};
             elseif story == 6;
                 outcomes(row,12) = {4};     
                 outcomes(row,13) = {'1b'};
                 outcomes(row,14) = {'Deserved'};
             end
         elseif strcmp(outcomes(row,6),'Block3');
             if story == 1;
                 outcomes(row,12) = {117};           
                 outcomes(row,13) = {'15c'};
                 outcomes(row,14) = {'Control'};
             elseif story == 2;
                 outcomes(row,12) = {108};           
                 outcomes(row,13) = {'14d'};
                 outcomes(row,14) = {'Control'};
             elseif story == 3;
                 outcomes(row,12) = {6}; 
                 outcomes(row,13) = {'1b'};
                 outcomes(row,14) = {'Control'};
             elseif story == 4;
                 outcomes(row,12) = {48};    
                 outcomes(row,13) = {'4d'};
                 outcomes(row,14) = {'Control'};
             elseif story == 5;
                 outcomes(row,12) = {42};    
                 outcomes(row,13) = {'4b'};
                 outcomes(row,14) = {'Control'};
             elseif story == 6;
                 outcomes(row,12) = {43};        
                 outcomes(row,13) = {'4c'};
                 outcomes(row,14) = {'Deserved'};
             end
         elseif strcmp(outcomes(row,6),'Block4');
             if story == 1;
                 outcomes(row,12) = {114};           
                 outcomes(row,13) = {'15b'};
                 outcomes(row,14) = {'Control'};
             elseif story == 2;
                 outcomes(row,12) = {1};         
                 outcomes(row,13) = {'1a'};
                 outcomes(row,14) = {'Deserved'};
             elseif story == 3;
                 outcomes(row,12) = {57};    
                 outcomes(row,13) = {'8c'};
                 outcomes(row,14) = {'Control'};
             elseif story == 4;
                 outcomes(row,12) = {91};        
                 outcomes(row,13) = {'12c'};
                 outcomes(row,14) = {'Deserved'};
             elseif story == 5;
                 outcomes(row,12) = {102};       
                 outcomes(row,13) = {'14b'};
                 outcomes(row,14) = {'Control'};
             elseif story == 6;
                 outcomes(row,12) = {32};        
                 outcomes(row,13) = {'3c'};
                 outcomes(row,14) = {'Undeserved'};
             end
         elseif strcmp(outcomes(row,6),'Block5');
             if story == 1;
                 outcomes(row,12) = {69} ;
                 outcomes(row,13) = {'10c'};
                 outcomes(row,14) = {'Control'};
             elseif story == 2;
                 outcomes(row,12) = {5};
                 outcomes(row,13) = {'1b'};
                 outcomes(row,14) = {'Undeserved'};
             elseif story == 3;
                 outcomes(row,12) = {12};
                 outcomes(row,13) = {'1d'};
                 outcomes(row,14) = {'Control'};
             elseif story == 4;
                 outcomes(row,12) = {37};
                 outcomes(row,13) = {'4a'};
                 outcomes(row,14) = {'Deserved'};
             elseif story == 5;
                 outcomes(row,12) = {118};
                 outcomes(row,13) = {'15d'};
                 outcomes(row,14) = {'Deserved'};
             elseif story == 6;
                 outcomes(row,12) = {112};   
                 outcomes(row,13) = {'15b'};
                 outcomes(row,14) = {'Deserved'};
             end
         elseif strcmp(outcomes(row,6),'Block6');
             if story == 1;
                 outcomes(row,12) = {77};
                 outcomes(row,13) = {'11b'};
                 outcomes(row,14) = {'Undeserved'};
             elseif story == 2;
                 outcomes(row,12) = {111};   
                 outcomes(row,13) = {'15a'};
                 outcomes(row,14) = {'Control'};
             elseif story == 3;
                 outcomes(row,12) = {120};
                 outcomes(row,13) = {'15d'};
                 outcomes(row,14) = {'Control'};
             elseif story == 4;
                 outcomes(row,12) = {23};    
                 outcomes(row,13) = {'2d'};
                 outcomes(row,14) = {'Undeserved'};
             elseif story == 5;
                 outcomes(row,12) = {40};
                 outcomes(row,13) = {'4b'};
                 outcomes(row,14) = {'Deserved'};
             elseif story == 6;
                 outcomes(row,12) = {50};
                 outcomes(row,13) = {'8a'};
                 outcomes(row,14) = {'Undeserved'};
             end
         elseif strcmp(outcomes(row,6),'Block7');
             if story == 1;
                 outcomes(row,12) = {71};
                 outcomes(row,13) = {'10d'};
                 outcomes(row,14) = {'Undeserved'};
             elseif story == 2;
                 outcomes(row,12) = {34};
                 outcomes(row,13) = {'3d'};
                 outcomes(row,14) = {'Deserved'};
             elseif story == 3;
                 outcomes(row,12) = {97};
                 outcomes(row,13) = {'14a'};
                 outcomes(row,14) = {'Deserved'};
             elseif story == 4;
                 outcomes(row,12) = {62};
                 outcomes(row,13) = {'10a'};
                 outcomes(row,14) = {'Undeserved'};
             elseif story == 5;
                 outcomes(row,12) = {94};
                 outcomes(row,13) = {'12d'};
                 outcomes(row,14) = {'Deserved'};
             elseif story == 6;
                 outcomes(row,12) = {10};
                 outcomes(row,13) = {'1d'};
                 outcomes(row,14) = {'Deserved'};
             end
         elseif strcmp(outcomes(row,6),'Block8');
             if story == 1;
                 outcomes(row,12) = {39};
                 outcomes(row,13) = {'4a'};
                 outcomes(row,14) = {'Control'};
             elseif story == 2;
                 outcomes(row,12) = {74};
                 outcomes(row,13) = {'11a'};
                 outcomes(row,14) = {'Undeserved'};
             elseif story == 3;
                 outcomes(row,12) = {51};
                 outcomes(row,13) = {'8a'};
                 outcomes(row,14) = {'Control'};
             elseif story == 4;
                 outcomes(row,12) = {7}; 
                 outcomes(row,13) = {'1c'};
                 outcomes(row,14) = {'Deserved'};
             elseif story == 5;
                 outcomes(row,12) = {90};
                 outcomes(row,13) = {'12b'};
                 outcomes(row,14) = {'Control'};
             elseif story == 6;
                 outcomes(row,12) = {20};
                 outcomes(row,13) = {'2c'};
                 outcomes(row,14) = {'Undeserved'};
             end
         elseif strcmp(outcomes(row,6),'Block9');
             if story == 1;
                 outcomes(row,12) = {110};   
                 outcomes(row,13) = {'15a'};
                 outcomes(row,14) = {'Undeserved'};
             elseif story == 2;
                 outcomes(row,12) = {107};   
                 outcomes(row,13) = {'14d'};
                 outcomes(row,14) = {'Undeserved'};
             elseif story == 3;
                 outcomes(row,12) = {64};
                 outcomes(row,13) = {'10b'};
                 outcomes(row,14) = {'Deserved'};
             elseif story == 4;
                 outcomes(row,12) = {81};
                 outcomes(row,13) = {'11c'};
                 outcomes(row,14) = {'Control'};
             elseif story == 5;
                 outcomes(row,12) = {76};
                 outcomes(row,13) = {'11b'};
                 outcomes(row,14) = {'Deserved'};
             elseif story == 6;
                 outcomes(row,12) = {70};
                 outcomes(row,13) = {'10d'};
                 outcomes(row,14) = {'Deserved'};
             end
         elseif strcmp(outcomes(row,6),'Block10');
             if story == 1;
                 outcomes(row,12) = {115};   
                 outcomes(row,13) = {'15c'};
                 outcomes(row,14) = {'Deserved'};
             elseif story == 2;
                 outcomes(row,12) = {85};
                 outcomes(row,13) = {'12a'};
                 outcomes(row,14) = {'Deserved'};
             elseif story == 3;
                 outcomes(row,12) = {75};
                 outcomes(row,13) = {'11a'};
                 outcomes(row,14) = {'Control'};
             elseif story == 4;
                 outcomes(row,12) = {13};
                 outcomes(row,13) = {'2a'};
                 outcomes(row,14) = {'Deserved'};
             elseif story == 5;
                 outcomes(row,12) = {78};    
                 outcomes(row,13) = {'11b'};
                 outcomes(row,14) = {'Control'};
             elseif story == 6;
                 outcomes(row,12) = {67};    
                 outcomes(row,13) = {'10c'};
                 outcomes(row,14) = {'Deserved'};
             end
         elseif strcmp(outcomes(row,6),'Block11');
             if story == 1;
                 outcomes(row,12) = {19};    
                 outcomes(row,13) = {'2c'};
                 outcomes(row,14) = {'Deserved'};
             elseif story == 2;
                 outcomes(row,12) = {66};    
                 outcomes(row,13) = {'10b'};
                 outcomes(row,14) = {'Control'};
             elseif story == 3;
                 outcomes(row,12) = {93};            
                 outcomes(row,13) = {'12c'};
                 outcomes(row,14) = {'Control'};
             elseif story == 4;
                 outcomes(row,12) = {14};    
                 outcomes(row,13) = {'2a'};
                 outcomes(row,14) = {'Undeserved'};
             elseif story == 5;
                 outcomes(row,12) = {11};    
                 outcomes(row,13) = {'1d'};
                 outcomes(row,14) = {'Undeserved'};
             elseif story == 6;
                 outcomes(row,12) = {41};    
                 outcomes(row,13) = {'4b'};
                 outcomes(row,14) = {'Undeserved'};
             end
         elseif strcmp(outcomes(row,6),'Block12');
             if story == 1;
                 outcomes(row,12) = {46};    
                 outcomes(row,13) = {'4d'};
                 outcomes(row,14) = {'Deserved'};
             elseif story == 2;
                 outcomes(row,12) = {31};    
                 outcomes(row,13) = {'3c'};
                 outcomes(row,14) = {'Deserved'};
             elseif story == 3;
                 outcomes(row,12) = {113};   
                 outcomes(row,13) = {'15b'};
                 outcomes(row,14) = {'Undeserved'};
             elseif story == 4;
                 outcomes(row,12) = {53};    
                 outcomes(row,13) = {'8b'};
                 outcomes(row,14) = {'Undeserved'};
             elseif story == 5;
                 outcomes(row,12) = {84};    
                 outcomes(row,13) = {'11d'};
                 outcomes(row,14) = {'Control'};
             elseif story == 6;
                 outcomes(row,12) = {15};    
                 outcomes(row,13) = {'2a'};
                 outcomes(row,14) = {'Control'};
             end
         elseif strcmp(outcomes(row,6),'Block13');
             if story == 1;
                 outcomes(row,12) = {88};    
                 outcomes(row,13) = {'12b'};
                 outcomes(row,14) = {'Deserved'};
             elseif story == 2;
                 outcomes(row,12) = {92};    
                 outcomes(row,13) = {'12c'};
                 outcomes(row,14) = {'Undeserved'};
             elseif story == 3;
                 outcomes(row,12) = {95};    
                 outcomes(row,13) = {'12d'};
                 outcomes(row,14) = {'Undeserved'};
             elseif story == 4;
                 outcomes(row,12) = {55};    
                 outcomes(row,13) = {'8c'};
                 outcomes(row,14) = {'Deserved'};
             elseif story == 5;
                 outcomes(row,12) = {44};    
                 outcomes(row,13) = {'4c'};
                 outcomes(row,14) = {'Undeserved'};
             elseif story == 6;
                 outcomes(row,12) = {38};    
                 outcomes(row,13) = {'4a'};
                 outcomes(row,14) = {'Undeserved'};
             end
         elseif strcmp(outcomes(row,6),'Block14');
             if story == 1;
                 outcomes(row,12) = {30};    
                 outcomes(row,13) = {'3b'};
                 outcomes(row,14) = {'Control'};
             elseif story == 2;
                 outcomes(row,12) = {17};    
                 outcomes(row,13) = {'2b'};
                 outcomes(row,14) = {'Undeserved'};
             elseif story == 3;
                 outcomes(row,12) = {60};    
                 outcomes(row,13) = {'8d'};
                 outcomes(row,14) = {'Control'};
             elseif story == 4;
                 outcomes(row,12) = {26};    
                 outcomes(row,13) = {'3a'};
                 outcomes(row,14) = {'Undeserved'};
             elseif story == 5;
                 outcomes(row,12) = {56};    
                 outcomes(row,13) = {'8c'};
                 outcomes(row,14) = {'Undeserved'};
             elseif story == 6;
                 outcomes(row,12) = {61};    
                 outcomes(row,13) = {'10a'};
                 outcomes(row,14) = {'Deserved'};
             end
         elseif strcmp(outcomes(row,6),'Block15');
             if story == 1;
                 outcomes(row,12) = {54};    
                 outcomes(row,13) = {'8b'};
                 outcomes(row,14) = {'Control'};
             elseif story == 2;
                 outcomes(row,12) = {21};    
                 outcomes(row,13) = {'2c'};
                 outcomes(row,14) = {'Control'};
             elseif story == 3;
                 outcomes(row,12) = {16};    
                 outcomes(row,13) = {'2b'};
                 outcomes(row,14) = {'Deserved'};
             elseif story == 4;
                 outcomes(row,12) = {104};   
                 outcomes(row,13) = {'14c'};
                 outcomes(row,14) = {'Undeserved'};
             elseif story == 5;
                 outcomes(row,12) = {49};    
                 outcomes(row,13) = {'8a'};
                 outcomes(row,14) = {'Deserved'};
             elseif story == 6;
                 outcomes(row,12) = {63};    
                 outcomes(row,13) = {'10a'};
                 outcomes(row,14) = {'Control'};
             end
         elseif strcmp(outcomes(row,6),'Block16');
             if story == 1;
                 outcomes(row,12) = {89};    
                 outcomes(row,13) = {'12b'};
                 outcomes(row,14) = {'Undeserved'};
             elseif story == 2;
                 outcomes(row,12) = {105};   
                 outcomes(row,13) = {'14c'};
                 outcomes(row,14) = {'Control'};
             elseif story == 3;
                 outcomes(row,12) = {58};    
                 outcomes(row,13) = {'8d'};
                 outcomes(row,14) = {'Deserved'};
             elseif story == 4;
                 outcomes(row,12) = {86};    
                 outcomes(row,13) = {'12a'};
                 outcomes(row,14) = {'Undeserved'};
             elseif story == 5;
                 outcomes(row,12) = {52};    
                 outcomes(row,13) = {'8b'};
                 outcomes(row,14) = {'Deserved'};
             elseif story == 6;
                 outcomes(row,12) = {119};   
                 outcomes(row,13) = {'15d'};
                 outcomes(row,14) = {'Undeserved'};
             end
         elseif strcmp(outcomes(row,6),'Block17');
             if story == 1;
                 outcomes(row,12) = {8}; 
                 outcomes(row,13) = {'1c'};
                 outcomes(row,14) = {'Undeserved'};
             elseif story == 2;
                 outcomes(row,12) = {59};    
                 outcomes(row,13) = {'8d'};
                 outcomes(row,14) = {'Undeserved'};
             elseif story == 3;
                 outcomes(row,12) = {72};    
                 outcomes(row,13) = {'10d'};
                 outcomes(row,14) = {'Control'};
             elseif story == 4;
                 outcomes(row,12) = {101};   
                 outcomes(row,13) = {'14b'};
                 outcomes(row,14) = {'Undeserved'};
             elseif story == 5;
                 outcomes(row,12) = {83};    
                 outcomes(row,13) = {'11d'};
                 outcomes(row,14) = {'Undeserved'};
             elseif story == 6;
                 outcomes(row,12) = {3}; 
                 outcomes(row,13) = {'1a'};
                 outcomes(row,14) = {'Control'};
             end
         elseif strcmp(outcomes(row,6),'Block18');
             if story == 1;
                 outcomes(row,12) = {18};    
                 outcomes(row,13) = {'2b'};
                 outcomes(row,14) = {'Control'};
             elseif story == 2;
                 outcomes(row,12) = {45};    
                 outcomes(row,13) = {'4c'};
                 outcomes(row,14) = {'Control'};
             elseif story == 3;
                 outcomes(row,12) = {65};    
                 outcomes(row,13) = {'10b'};
                 outcomes(row,14) = {'Undeserved'};
             elseif story == 4;
                 outcomes(row,12) = {82};    
                 outcomes(row,13) = {'11d'};
                 outcomes(row,14) = {'Deserved'};
             elseif story == 5;
                 outcomes(row,12) = {103};   
                 outcomes(row,13) = {'14c'};
                 outcomes(row,14) = {'Deserved'};
             elseif story == 6;
                 outcomes(row,12) = {35};    
                 outcomes(row,13) = {'3d'};
                 outcomes(row,14) = {'Undeserved'};
             end
         elseif strcmp(outcomes(row,6),'Block19');
             if story == 1;
                 outcomes(row,12) = {96};    
                 outcomes(row,13) = {'12d'};
                 outcomes(row,14) = {'Control'};
             elseif story == 2;
                 outcomes(row,12) = {27};    
                 outcomes(row,13) = {'3a'};
                 outcomes(row,14) = {'Control'};
             elseif story == 3;
                 outcomes(row,12) = {33};    
                 outcomes(row,13) = {'3c'};
                 outcomes(row,14) = {'Control'};
             elseif story == 4;
                 outcomes(row,12) = {99};    
                 outcomes(row,13) = {'14a'};
                 outcomes(row,14) = {'Control'};
             elseif story == 5;
                 outcomes(row,12) = {106};   
                 outcomes(row,13) = {'14d'};
                 outcomes(row,14) = {'Deserved'};
             elseif story == 6;
                 outcomes(row,12) = {116};   
                 outcomes(row,13) = {'15c'};
                 outcomes(row,14) = {'Undeserved'};
             end
         elseif strcmp(outcomes(row,6),'Block20');
             if story == 1;
                 outcomes(row,12) = {47};    
                 outcomes(row,13) = {'4d'};
                 outcomes(row,14) = {'Undeserved'};
             elseif story == 2;
                 outcomes(row,12) = {9}; 
                 outcomes(row,13) = {'1c'};
                 outcomes(row,14) = {'Control'};
             elseif story == 3;
                 outcomes(row,12) = {29};    
                 outcomes(row,13) = {'3b'};
                 outcomes(row,14) = {'Undeserved'};
             elseif story == 4;
                 outcomes(row,12) = {87};    
                 outcomes(row,13) = {'12a'};
                 outcomes(row,14) = {'Control'};
             elseif story == 5;
                 outcomes(row,12) = {22};    
                 outcomes(row,13) = {'2d'};
                 outcomes(row,14) = {'Deserved'};
             elseif story == 6;
                 outcomes(row,12) = {80};    
                 outcomes(row,13) = {'11c'};
                 outcomes(row,14) = {'Undeserved'};
             end
         end
         row = row + 1;
     end
     header = {'Subject' 'Session' 'StoryText' 'Set' 'StoryNum' 'Block' 'FullStory' 'LineNum' 'RT' 'RTTime' 'StoryText2' 'TotalStoryNum' 'StoryGroup' 'StoryType'};
     finalDataRows = totalrows + 1;
     finalData(1,[1:14])=header(1,[1:14]);
     finalData([2:finalDataRows],[1:14])=outcomes([1:totalrows],[1:14]);
     finalData(:,7)=[];
     T = table(finalData);
     writetable(T,'FinalData.csv','Delimiter',',');
 end

SPSS Macros

My initial data analysis training was done in SPSS. After more than five years of using the menus and syntax commands for data analysis, I started developing macros for preliminary data cleaning steps. I use the macros shown below to cut down on the amount of time I spend identifying and dealing with both multivariate and univariate outliers.

 *These macros and syntax below winsorize outliers, identify multivariate outliers, and then create a new dataset excluding the multivariate outliers.
 
 *This is how I winsorized (all of the steps were done in the winsorizing macro below):
 1. Take absolute values of all z-scores
 2. Rank the absolute vaules from highest (1) to lowest
 3. Find the rank for the highest absolute value that is below the cut-off (in this example, 3)
 4. Use the following formula to calculate the winsorized z-scores (NOTE: if the original z-score was negative, be sure to multiply the final value by -1):
     ((3-limit)/rank limit)*distance+limit
         limit = highest absolute value below 3
         rank limit = the rank associated with the limit value
         distance = rank limit - rank of the z-score for the outlier
 5. Use the new z-scores to compute new values for the outliers (z*SD+M).
 *This method ensures that individual scores maintain their relative position in the distribution. 
 DEFINE winsorizing (vars = !CHAREND('/') / cut = !CMDEND)
 
 PRESERVE.
 SET RESULTS OFF ERRORS OFF.
 
 !DO !i !IN (!vars)
     COMPUTE H = !cut.
     COMPUTE L = H*-1.
     EXECUTE.
     DESCRIPTIVES  VARIABLES = !i /SAVE.
     COMPUTE Z = !CONCAT("Z",!i).
     EXECUTE.
     COMPUTE AZ = ABS(Z).
     EXECUTE.
     RANK VARIABLES=AZ (D) /RANK into RAZ /PRINT=YES /TIES=LOW.
     IF AZ LT H RAZ2 = RAZ.
     IF AZ LT H AZ2 = AZ.
     EXECUTE.
     AGGREGATE /OUTFILE=* MODE=ADDVARIABLES OVERWRITE=YES /M=MEAN(!i) /S=SD(!i) /rankLimit = MIN(RAZ2) /limit = MAX(AZ2).
     COMPUTE !CONCAT("wZ",!i)  = Z.
     IF Z GE H !CONCAT("wZ",!i) = ((H - limit)/rankLimit)*(rankLimit - RAZ) + limit.
     IF Z LE L !CONCAT("wZ",!i) = (((H - limit)/rankLimit)*(rankLimit - RAZ) + limit)*(-1).
     EXECUTE.
     IF AZ LT H !CONCAT("w",!i) = !i.
     IF AZ GE H !CONCAT("w",!i) = M + S*!CONCAT("wZ",!i).
     EXECUTE.
     DELETE VARIABLES Z AZ RAZ RAZ2 AZ2 M S rankLimit limit H L.
     EXECUTE.
 !DOEND
 
 RESTORE.
 
 !ENDDEFINE.
 
 *Use the compute statement below to set the z-score cut-off.
 COMPUTE val = 3. 
 EXECUTE.
 
 *Use the syntax below to call the winsorizing macro.
 winsorizing vars = X Y Z / cut = val.
     /*The varaibles the macro returns are the Z-score for the original variable (Z), the winsorized Z-score (wZ), and the winsorized value (w).
 DELETE VARIABLES val.
 EXECUTE.
 
 
 *Counting univariate outliers.
 DEFINE countOutliers (vars = !CMDEND)
 !DO !i !IN (!vars)
 IF !CONCAT("Z",!i) GE 3 OR !CONCAT("Z",!i) LE -3 !CONCAT("O",!i) = 1.
 EXECUTE.
 !DOEND
 !ENDDEFINE.
 
 countOutliers vars = X Y Z.
 
 
 *I then screened for multivariate outliers using the criteria described by Tabachnick and Fidell (2007):
 if the proportion of Mahalanobis Distance scores that fall below a given score is less than .001, then that score is considered a multivariate outlier.
 
 DEFINE multivariate (dv = !CHAREND('/') / iv = !CHAREND('/') / ivNUM = !CHAREND('/') / type = !CHAREND('/'))
 
 ***MACRO NOTES***
 *dv: list of outcome variables
 *iv: list of predictor variables
 *ivNUM: the number of predictor variables
 *type: 1 = original, 2 = winsorized data (univariate), 3 = data without univariate outliers, 4 = data without multivariate outliers
 *Make sure you end each of the macro components with a '/'.
 *For example, if you have 2 predictors and 2 mediators, and you are running the macro on the original data, then the macro should look like this:
 *multivariate dv = outcomes / iv = predictors / ivNUM = 2 / type = 1. (Check this...number of predictors seems wrong).
 
 PRESERVE.
 SET RESULTS OFF ERRORS OFF.
 
 !DO !i !IN (!dv)
 REGRESSION
    /MISSING LISTWISE
    /CRITERIA=PIN(.05) POUT(.10)
    /NOORIGIN
    /DEPENDENT !i
    /METHOD=ENTER !iv
    /SAVE MAHAL.
 COMPUTE p_MAH_1 = 1 - cdf.chisq(MAH_1,!ivNUM).
 COMPUTE !CONCAT("mv.",!i,!type) = p_MAH_1.
 EXECUTE.
 IF !CONCAT("mv.",!i,!type) LT .001 !CONCAT("m0.",!i,!type) = 1.
 EXECUTE.
 DELETE VARIABLES p_MAH_1 MAH_1.
 EXECUTE.
 !DOEND
 
 RESTORE.
 
 !ENDDEFINE.
 
 *The syntax below screens for multivariate outliers using unwinsorized variables.
 multivariate dv = wY / iv = wX wZ / ivNUM = 2 / type = 2.
 *Only 4 multivariate outliers. 
 
 
 *Creating dataset without multivariate outliers.
 DATASET COPY  noMV.
 DATASET ACTIVATE  noMV.
 FILTER OFF.
 USE ALL.
 SELECT IF (MISSING(m0.wY)).
 EXECUTE.

MPlus

My initial training in SEM and path analysis was done using MPlus. I have used this program to analyze a variety of complex models, including moderation with latent factors (see Drolet & Drolet, 2019). The code below is for a recent project where we had to use WLSMV estimation to examine indirect effects of continuous predictors on a binary outcome. Unlike most other models I have run in MPlus, this model involved the use of WRMR (instead of SRMR) as an indicator of model fit. I also had to use different methods than for ML models for declaring indirect effects and getting Chi-square difference tests to compare models.

 title: BinaryOutcomeModel
 
 data: File = /Users/carolinedrolet/Desktop/KeeperData2.dat;
 
 variable: Names = ID
 Culcomp
 Attitude
 Norm
 PBC
 Intent
 WantFIT
 C_GvTL
 C_LvTL
 C_TGvTL;
 
 Usevariables =
 Culcomp
 Attitude
 Norm
 PBC
 Intent
 WantFIT
 C_GvTL
 C_LvTL
 C_TGvTL;
 
 categorical = WantFIT;
 
 Missing Are
 Culcomp
 Attitude
 Norm
 PBC
 Intent
 WantFIT
 C_GvTL
 C_LvTL
 C_TGvTL
  (-999);
 
 analysis: ESTIMATOR =  WLSMV;
 !difftest = mydiff.dat;
 BOOTSTRAP=10000;
 
 model:
 Attitude on Culcomp(a1)
 C_GvTL
 C_LvTL
 C_TGvTL;
 
 Norm on Culcomp(a2)
 C_GvTL
 C_LvTL
 C_TGvTL;
 
 PBC on Culcomp(a3)
 C_GvTL
 C_LvTL
 C_TGvTL;
 
 Intent on Culcomp(a4)
 !Culcomp@0
 Attitude(b1)
 Norm(b2)
 PBC(b3)
 C_GvTL
 C_LvTL
 C_TGvTL
 ;
 
 WantFIT on !Culcomp@0
 !Culcomp
 Intent(b4)
 !PBC@0
 !PBC
 C_GvTL
 C_LvTL
 C_TGvTL
 ;
 
 Attitude with Norm PBC;
 
 Norm with PBC;
 
 model constraint:
 new (ccEND);
 ccEND = a4*b4;
 
 new (attEND);
 attEND = a1*b1*b4;
 
 new (normEND);
 normEND = a2*b2*b4;
 
 !savedata:
 !difftest is mydiff.dat;
 
 output: SAMPSTAT STANDARDIZED CINTERVAL(BCBOOTSTRAP)
 ;

HTML, CSS, and javascript

My greatest coding undertaking to date was my creation of a statistics practice website for undergraduate psychology students (statisticspractice.ca). The entire website was built from scratch using a combination of html, CSS, and javascript. For each task, data are randomly generated each time the page loads, providing a seemingly infinite number of unique practice questions. The text entry boxes provide immediate feedback about whether answers are correct or not, and students can also click “Show Answers” to see the solutions if they get stuck. There is also a calculator in the corner so that students can practice on their phones without having to switch between the browser and the calculator app. Much of the development across versions of the website was based on student feedback, helping to make the experience as accessible to them as possible. We also found that students who performed poorly on the first exam and who used the online questions to study for the next exam scored higher than those who performed poorly on the first exam but who did not use the online questions.

In addition to my stats practice website, I also developed custom html, CSS, and javascript for use in Qualtrics and MTurk studies. Below is an example of a function I wrote for a colleague who was running a reaction-time study that involved a Stroop task. Because the reaction-time measurements were reliant on key presses, it was important that participants were not completing the study on a mobile device. The function that I wrote would check whether they were on a mobile device and, if they were, would tell them they could not take the study before sending them back to the list of available hits. I have also written versions of this code for use on Qualtrics, so that participants can save their progress and then continue the study from their computer.

 <!DOCTYPE html>
 <html>
 <body onload="detectDevice()">
 
 Nothing should happen unless the person is on a mobile device.
 If they are on a mobile device, the script tells them that they cannot
 complete the survey on a mobile device and takes them back to the 
 list of available HITs on Mturk.
 
 <script>
 function detectDevice() {
  var z = navigator.userAgent.match(/(iPad)|(iPhone)|(iPod)|(android)|(webOS)/i);
     if (z==null) {
         }
     else {
      alert("You cannot complete this survey on a mobile device");
         location.replace("https://www.mturk.com/mturk/findhits?match=false");
         }
      
 }
 </script>
 
 </body>
 </html>