Emotional Impact of Memory Part One

Processing an image database for use in a experiment to induce an emotional state in particpants.

Research Protocol

library(tidyverse)
library(stringr)
library(knitr)
library(plotly)
library(gridExtra)
library(inspectdf)
library(DT)

The following was the code used to prepare images from the IAPS database for a experiment on pattern separation. The participants were seated in front of a PC and went through three tasks: Encoding, retreival and validation. We were provided with a folder of approved images and a text file with unapproved images.

Raw text to selected IAPS images

A raw text file was provided with the IAPS database image details I then used a script to then compare the images in the memory task folder and made a raw dataframe with all the IAPS data. There are 200 images overall. Old, new and fake conditions were added based on coding from the images folder.

iaps_dataframe_images <- read_csv("data/iaps_raw.csv") #List of all IAPS images
RP_images <- read_csv("data/new_old_images.csv") #list of images used in our research protocol
RP_images <- as.matrix(RP_images) # convert to matrix


ENC_orig_RET_New <- na.omit(str_match(RP_images, "^[[:digit:]]+\\.*[[:digit:]]*$")) # _ENC_ORIGINAL_50 whats left over RET_UNSEEN_NEW
RET_PS_a <- na.omit(str_match(RP_images, "[[:digit:]]{4}a$")) # _RET_PS_a 50
ENC_ORIGINAL_b <- na.omit(str_match(RP_images, "[[:digit:]]{4}b$")) # _ENC_ORIGINAL_b 50
# RET_UNSEEN_NEW

all_images_list <- cbind(c(ENC_orig_RET_New, RET_PS_a, ENC_ORIGINAL_b))

# match IAPS numbers to ones we have selected for RP
group39_df <- filter(iaps_dataframe_images, nr %in% str_extract(all_images_list, "\\d{4}"))

Negative and Neutral Images

The following functions compare the iaps_dataframe_images using the nr column numbers to the vectors made previously above.

Highly negative and neutral images were coded by looking at the means and then coding highly aroused negative images that have a mean greater than 4.5. All neutral low neutral images were coded with valence means less than 4.0.

A dataframe of all the images being used in the experiment are then stored into the group39_df. ENC_RET_ORIG_UNSEEN needs to be seperated with 50 images to be used in the retrieval task.

group39_df_mutate <- group39_df %>% #Create Negative and Neutral cases
  select_all() %>% 
  mutate(
    Emotion = case_when(
      aromn > 4.5  ~ "Negative", 
      valmn > 4.0 ~ "Neutral"))

group39_df <- group39_df_mutate

# Core master list of all images 

core_images_df <- filter(group39_df, Condition != "RET_PS_a")
# 

We have three tasks: Encoding, Retreival and Validation. The images that were marked a or b are the ones that have been photoshopped to look like their counterparts. However, we need to take the 100 images that are not marked and split them so that half are used in the encoding and the ones not used, introduced into the retrieval task and marked as new/unseen.

The group39_df also has all the negative and neutral emotion conditions attached to eaech image so we can now filter accordingly.

encoding_list <- filter(group39_df, Condition == "ENC_RET_ORIG_UNSEEN") %>% arrange(Emotion) 
# filter the raw list by first 100


nrowgen<-function(x,y) #Function to sort a list by every second row
{
  n<-nrow(x)
  b<-seq(1,n,y)
  r<-length(b)
  c=data.frame()
  {
    for(i in 1:r)
    {
      abc<-x[b[i],]
      c<-rbind(c,abc)
      
    }
    return(c)
  }
}



# RET TASK 50 images
RET_UNSEEN_NEW <- nrowgen(encoding_list, 2) 
# select every second row - original DF arranged by emotion


# ENC TASK 50 images
ENC_ONLY_ORIG <- anti_join(encoding_list, RET_UNSEEN_NEW)
# match those columns that arent in the unseen list


# 50 Fake photoshopped images for the ret task 
RET_FAKE_a <- filter(group39_df, Condition == "RET_PS_a")

ENC_ORIG_b <- filter(group39_df, Condition == "ENC_ORIGINAL_b")


# Validation task
VAL_TASK <- filter(group39_df, Condition == "RET_PS_a") %>% arrange(nr)

RET_SEEN <- ENC_ONLY_ORIG


# Change the condition name
RET_SEEN$Condition[RET_SEEN$Condition == "ENC_RET_ORIG_UNSEEN"] <- "RET_SEEN"

RET_FAKE_a$Condition[RET_FAKE_a$Condition == "RET_PS_a"] <- "RET_FAKE_a"

RET_UNSEEN_NEW$Condition[RET_UNSEEN_NEW$Condition == "ENC_RET_ORIG_UNSEEN"] <- "RET_UNSEEN_NEW"

ENC_ONLY_ORIG$Condition[ENC_ONLY_ORIG$Condition == "ENC_RET_ORIG_UNSEEN"] <- "ENC_ONLY"

We now have vectors with all the information needed. Below are the dataframes for eaech task and then joined together to create the main spreadsheet for use in the lab.

# Full join of tables

abc <- full_join(ENC_ONLY_ORIG, ENC_ORIG_b)

def <- full_join(RET_UNSEEN_NEW, RET_FAKE_a)

xyz <- full_join(abc, def)

Task_Spreadsheet <- full_join(xyz, RET_SEEN)

datatable(Task_Spreadsheet, class = 'cell-border stripe'
, caption = 'All IAPS database images used for the experiment')
All IAPS database images used for the experiment
Content nr valmn valsd aromn arosd dom1mn dom1sd dom2mn dom2sd set Condition Emotion

Visual Distribution of Data

inspect_cat(Task_Spreadsheet, show_plot = TRUE)
## # A tibble: 3 x 5
##   col_name    cnt common     common_pcnt levels            
##   <chr>     <int> <chr>            <dbl> <named list>      
## 1 Condition     5 ENC_ONLY          20   <tibble [5 x 3]>  
## 2 Content     114 Mutilation        10.4 <tibble [114 x 3]>
## 3 Emotion       2 Negative          50   <tibble [2 x 3]>

Checks for image condition counts

kable(Task_Spreadsheet %>% 
  select(valmn, aromn, dom1mn, Emotion) %>% 
  group_by(Emotion) %>% 
  count(Emotion))
Emotion n
Negative 125
Neutral 125
#Check number of images for each type  
kable(Task_Spreadsheet %>% 
  select(valmn, aromn, dom1mn, Condition) %>% 
  group_by(Condition) %>% 
  count(Condition))
Condition n
ENC_ONLY 50
ENC_ORIGINAL_b 50
RET_FAKE_a 50
RET_SEEN 50
RET_UNSEEN_NEW 50

Descriptives of pooled Means and SDs by Negative and Neutral Images.

#Means and SDs
kable(core_images_df %>% 
  select(valmn, valsd, aromn, arosd, dom1mn, dom1sd, Emotion) %>% 
  group_by(Emotion) %>% 
  summarise(ValMean = mean(valmn)
            , Valsd = sd(valsd)
            , ArousMean = mean(aromn)
            , ArouSD = sd(arosd)
            , DomMean = mean(na.omit(dom1mn)
            , DomSD = sd(dom1sd)))) 
Emotion ValMean Valsd ArousMean ArouSD DomMean
Negative 2.226400 0.3180505 6.440667 0.205209 3.330000
Neutral 5.226667 0.2736360 2.909600 0.207334 5.997759

Scatterplot of all Images with mean scores

p <- subplot(
    plot_ly(core_images_df, x = ~ Content, y = ~ aromn, type = "scatter") %>% 
        add_trace(y = ~ aromn) %>%
        layout(yaxis = list(title = "Arousal")),
  plot_ly(core_images_df, x = ~Content, y = ~ valmn, type = "scatter") %>% 
    add_trace(y = ~valmn) %>% 
    layout(yaxis = list(title = "Valence")),
  plot_ly(core_images_df, x = ~Content, y = ~ dom1mn, type = "scatter") %>% 
    add_trace(y = ~dom1mn) %>%
    layout(yaxis = list(title = "Dominance")),
  titleY = TRUE, shareX = TRUE, nrows = 3
) %>% hide_legend()

p
  • Currently not rendering in Hugo

Unvalidated Data

Following are the image codes that for the pictures that are edited to look like thier fake counterparts that need approval from ethics.

unapproved_IAPS_raw <- as.matrix(c(2036,3030,3069,3130,3530,6021,6838,7187,8485,
                                   2038,3059,3071,3131,5390,6212,7031,7491,9252,
                                   2320,3062,3080,3150,5500,6370,7035,7493,9425,
                                   2580,3063,3100,3268,5711,6510,7038,7500,9433,
                                   3010,3064,3103,3212,5725,6520,7039,7547,9904,
                                   3016,3068,3110,3500,5750,6550,7055,7700))


unapproved_images_df <- data.frame(unapproved_IAPS_raw) # convert to data frame

kable(count(unapproved_images_df)) # check the number of images
n
53
#Filter a new list with only new unapproved images
non_validated_iaps_all <- filter(group39_df, nr %in% unapproved_IAPS_raw)


# filter for only negative images
non_validated_iaps <- filter(group39_df
                             , nr %in% unapproved_IAPS_raw
                             , Condition != "RET_PS_a"
                             , Emotion == "Negative") %>% 
  arrange(nr)

datatable(non_validated_iaps, class = 'cell-border stripe', caption = 'Unapproved Negative IAPS')
Avatar
Aaron Willcox
Student

Interests include data wrangling with R and research into neurodevelopmental disorders particularly adult ADHD.