In [1]:
import os
import pandas as pd
import numpy as np
%load_ext rpy2.ipython
%R library(IAT)
Out[1]:
In [2]:
import pyiat
Example data from the Death Implicit Association Test
Nock, M.K., Park, J.M., Finn, C.T., Deliberto, T.L., Dour, H.J., & Banaji, M.R. (2010). Measuring the suicidal mind: Implicit cognition predicts suicidal behavior. Psychological Science, 21(4), 511–517. https://doi.org/10.1177/0956797610364762
pyiat will work with any IAT data.
In [3]:
d=pd.read_csv('iat_data.csv',index_col=0)
In [4]:
d.head()
Out[4]:
In [5]:
#Number of trials per subject
#Note that Subject 1 has too few trials
d.groupby('subjnum').subjnum.count().head()
Out[5]:
In [6]:
#Number of subjects in this data set
d.subjnum.unique()
Out[6]:
In [7]:
#Conditions
d.condition.unique()
Out[7]:
In [8]:
#Blocks
d.block.unique()
Out[8]:
In [9]:
#Correct coded as 1, errors coded as 0 in correct column
d.correct.unique()
Out[9]:
Blocks 0,1 & 4 - which contain conditions 'Death,Life', 'Not Me,Me', 'Life,Death' are practice blocks, meaning they do not contain relevant data because they do not contrast the different categories.
Therefore, we will enter blocks 2,3,5,6 and conditions 'Life/Not Me,Death/Me', 'Death/Not Me,Life/Me' into analyze_iat.
We are entering the "correct" column, which contains 1 for correct and 0 for errors. We could enter the "errors" column and then just set the error_or_correct argument to 'error.'
Finally, we have the option to return the total number and percentage of trials that are removed because they are either too fast (default : 400ms) or too slow (default : 10000ms). This will return the number and percentage across all subjects and across just subjects that do not receive a flag indicating they had poor performance on some metric.
In [10]:
d1,fs1=pyiat.analyze_iat(d,subject='subjnum',rt='latency',condition='condition',correct='correct'\
,cond1='Death/Not Me,Life/Me',cond2='Life/Not Me,Death/Me'\
,block='block',blocks=[2,3,5,6],fastslow_stats=True)
In [11]:
d1.iloc[:,0:14].head()
Out[11]:
In [12]:
d1.iloc[:,14:21].head()
Out[12]:
In [13]:
d1.iloc[:,21:28].head()
Out[13]:
In [14]:
d1.iloc[:,28:35].head()
Out[14]:
In [15]:
d1.iloc[:,35].to_frame().head()
Out[15]:
In [16]:
d1.iloc[:,36:58].head()
Out[16]:
In [17]:
d1.iloc[:,58].to_frame().head()
Out[17]:
In [18]:
d1.iloc[:,59:62].head()
Out[18]:
In [19]:
#Prepare data to enter into r package - need to have blocks be a string and need to divide data into 2 separate
#dataframes for people that received "Death,Me" first and for those that received "Life,Me" first.
d['block_str']=d.block.astype(str)
d1_r_subn=d[(d.condition=='Death/Not Me,Life/Me')&(d.block>4)].subjnum.unique()
d1_r=d[d.subjnum.isin(d1_r_subn)]
d2_r_subn=d[(d.condition=='Life/Not Me,Death/Me')&(d.block>4)].subjnum.unique()
d2_r=d[d.subjnum.isin(d2_r_subn)]
%R -i d1_r
%R -i d2_r
In [20]:
%%R
dscore_first <- cleanIAT(my_data = d1_r,
block_name = "block_str",
trial_blocks = c("2","3", "5", "6"),
session_id = "subjnum",
trial_latency = "latency",
trial_error = "errors",
v_error = 1, v_extreme = 2, v_std = 1)
dscore_second <- cleanIAT(my_data = d2_r,
block_name = "block_str",
trial_blocks = c("2","3", "5", "6"),
session_id = "subjnum",
trial_latency = "latency",
trial_error = "errors",
v_error = 1, v_extreme = 2, v_std = 1)
r_dsc <- rbind(dscore_first, dscore_second)
In [21]:
%R -o dscore_first
%R -o dscore_second
#Then we need to combine the separate dataframes
#One of these the scores are flipped so need to flip back
dscore_second.IAT=dscore_second.IAT*-1
iat_r_dsc=pd.concat([dscore_first,dscore_second])
iat_r_dsc.index=iat_r_dsc.subjnum
iat_r_dsc=iat_r_dsc.sort_index()
In [22]:
py_r_iat=pd.concat([d1.dscore,iat_r_dsc.IAT],axis=1)
py_r_iat.head()
Out[22]:
In [23]:
#Correlation between pyiat (dscore) and R package (IAT) = 1
py_r_iat.corr()
Out[23]:
In [24]:
fs1
Out[24]:
In [25]:
d2,fs2=pyiat.analyze_iat(d,subject='subjnum',rt='latency',condition='condition',correct='correct'\
,cond1='Death/Not Me,Life/Me',cond2='Life/Not Me,Death/Me'\
,block='block',blocks=[2,3,5,6],fastslow_stats=True,each_stim=True,stimulus='trial_word')
In [26]:
d2.iloc[:,59:].head()
Out[26]:
In [27]:
d3,fs3=pyiat.analyze_iat(d,subject='subjnum',rt='latency',condition='condition',correct='correct'\
,cond1='Death/Not Me,Life/Me',cond2='Life/Not Me,Death/Me'\
,fastslow_stats=True,weighted=False)
In [28]:
d3.iloc[:,24:].head()
Out[28]:
In [29]:
d4,fs4=pyiat.analyze_iat(d,subject='subjnum',rt='latency',condition='condition',correct='correct'\
,cond1='Death/Not Me,Life/Me',cond2='Life/Not Me,Death/Me'\
,fastslow_stats=True,each_stim=True,stimulus='trial_word',weighted=False)
In [30]:
d4.iloc[:,26:].head()
Out[30]:
pyiat can also produce D scores and poor performance flags for the Brief IAT (BIAT), according to Nosek, et al., 2014 scoring procedures (trials greater than 2 sec are changed to 2 sec, trials less than 400ms are changed to 400ms), with some options. The first x (default 4) trials of each block can be removed or not or you can determine how many trials should be removed from the beginning of each block, if any. You can set the pct flags. One issue with BIAT flags in pyiat is that currently flags for fast and slow trials use the same cutoff pct. Recommended scoring procedures (Nosek et al. 2014) recommend a flag for fast trials but not slow. This is not currently possible in pyiat. However, you can see the pct of slow and fast trials and create your own flags from this information.
The BIAT code can take either 2, 4, or 6 blocks (depending what is listed in the blocks argument) and will dynamically adjust to however many blocks it is given.
Results of pyiat BIAT D scores were checked against D scores sent to me from U of Virginia.
In [31]:
bd=pd.read_csv('biat_data.csv',index_col=0)
In [32]:
bd.head()
Out[32]:
In [33]:
biatd1,biatfsl=pyiat.analyze_iat(bd,subject='subn',rt='RT',condition='pair',\
correct='errors',error_or_correct='error'\
,cond2='(unnamed)/Death,Me/Life',cond1='(unnamed)/Life,Me/Death'\
,block='block_num',blocks=[0, 1, 2, 3,4,5],biat=True,biat_rmv_xtrls=4,biat_trl_num='trl_number',fastslow_stats=True)
In [34]:
biatd1.iloc[:,-5:].head()
Out[34]:
In [35]:
biatd1stim,biatfslstim=pyiat.analyze_iat(bd,subject='subn',rt='RT',condition='pair',\
correct='errors',error_or_correct='error'\
,cond2='(unnamed)/Death,Me/Life',cond1='(unnamed)/Life,Me/Death'\
,block='block_num',blocks=[0, 1, 2, 3,4,5],biat=True,biat_rmv_xtrls=4,\
biat_trl_num='trl_number',fastslow_stats=True,each_stim=True,stimulus='word',weighted=False)
In [36]:
#The first subject had only one block and you can see the repeated numbers
biatd1stim.iloc[:,-15:].head()
Out[36]:
In [ ]: