8 beh :: rating variability

Those with greater variability have greater placebo effects.

  • Harris (2005) Effect of variability in the 7-day baseline pain diary on the assay sensitivity of neuropathic pain randomized clinical trials: An ACTTION study. doi: 10.1002/art.21407
  • Farrar et al (2014) Effect of variability in the 7-day baseline pain diary on the assay sensitivity of neuropathic pain randomized clinical trials: An ACTTION study

load libraries

# parameters ___________________________________________________________________
main_dir <- dirname(dirname(getwd()))
datadir <- file.path(main_dir, 'data', 'beh', 'beh02_preproc')
analysis_dir <- file.path(main_dir, "analysis", "mixedeffect", "model09_var", as.character(Sys.Date()))
dir.create(analysis_dir, showWarnings = FALSE, recursive = TRUE)
subject_varkey <- "src_subject_id"
iv <- "param_cue_type"
dv <- "event03_RT"
dv_keyword <- "RT"
xlab <- ""
taskname <- "pain"
ylab <- "ratings (degree)"
subject <- "subject"
exclude <- "sub-0001"
# 1. load data _________________________________________________________________
data <- cueR::df_load_beh(datadir,
                            taskname = taskname,
                            subject_varkey = subject_varkey,
                            iv = iv,
                            exclude = exclude)

column_mapping <- c("src_subject_id" = "subject", 
                    "session_id" = "ses", 
                    "param_run_num" = "run", 
                    "param_task_name" = "runtype",
                    "param_cue_type" = "cue", 
                    "param_stimulus_type" = "stimintensity")
data <- df_rename_columns(data, column_mapping)
data_centered <- cueR::compute_enderstofighi(data, sub="subject",
                                    outcome = "event04_actual_angle",expect= "event02_expect_angle",
                                    ses = "ses", run = "run")

8.1 Analysis 1: Pain display distribution of data

Let’s look at the distribution of the data. X axis: Y axis:

# remove NA values first
df.centered_NA <- data_centered %>% filter(!is.na(OUTCOME))  # Remove NA values
head(df.centered_NA)
## # A tibble: 6 × 75
##   src_subject_id session_id param_task_name param_run_num param_counterbalance…¹
##            <int>      <int> <chr>                   <int>                  <int>
## 1              2          1 pain                        1                      3
## 2              2          1 pain                        1                      3
## 3              2          1 pain                        1                      3
## 4              2          1 pain                        1                      3
## 5              2          1 pain                        1                      3
## 6              2          1 pain                        1                      3
## # ℹ abbreviated name: ¹​param_counterbalance_ver
## # ℹ 70 more variables: param_counterbalance_block_num <int>,
## #   param_cue_type <chr>, param_stimulus_type <chr>, param_cond_type <int>,
## #   param_trigger_onset <dbl>, param_start_biopac <dbl>, ITI_onset <dbl>,
## #   ITI_biopac <dbl>, ITI_duration <dbl>, event01_cue_onset <dbl>,
## #   event01_cue_biopac <dbl>, event01_cue_type <chr>,
## #   event01_cue_filename <chr>, ISI01_onset <dbl>, ISI01_biopac <dbl>, …

8.1.1 Sort based on Median Outcome rating order

# Sort the data by median "outcome" in ascending order
sorted_data <- df.centered_NA %>%
  group_by(subject) %>%
  summarize(median_outcome = median(OUTCOME, na.rm = TRUE)) %>%
  arrange(median_outcome) %>%
  select(subject)

# Reorder the "subject" factor based on the sorted order
df.centered_NA$subject <- factor(df.centered_NA$subject, levels = sorted_data$subject)

# Create the ggplot
g <- ggplot(df.centered_NA, aes(x = subject, y = OUTCOME, fill = subject)) +
  geom_boxplot(outlier.shape = NA, width = 1.2, position = position_dodge(2)) +  
  geom_jitter(width = .1, alpha = 0, size = 1) +
  labs(x = "Subject", y = "Pain Outcome Rating") +
  theme_classic() +
  theme(legend.position = "none") +
  scale_x_discrete(breaks = NULL) 

# Convert ggplot object to a plotly object with hover information
g_plotly <- ggplotly(ggplot_largetext(g), tooltip = c("x", "y"))
## Warning: `position_dodge()` requires non-overlapping x intervals
## Warning: Aspect ratios aren't yet implemented, but you can manually set a
## suitable height/width

## Warning: Aspect ratios aren't yet implemented, but you can manually set a
## suitable height/width
g_plotly

8.2 calculate cue effect

8.3 Q. Do those who use the scale widely show greater cue effects?

df.centered_NA$run_order <- NA
dv <- "OUTCOME"

  # 3. calculate difference scores and summarize _____________________________
df.centered_NA$run_order[df.centered_NA$run > 3] <- "a"
df.centered_NA$run_order[df.centered_NA$run <= 3] <- "b"
sub_diff <- subset(df.centered_NA, select = c(
    "subject", "ses", "run",
    "runtype", "cue",
    "stimintensity", dv
))

# drop NA
sub_diff_NA <- sub_diff %>% filter(!is.na(dv)) 
subjectwise <- meanSummary(sub_diff_NA, c(
    "subject", "ses", "run",
    "runtype", "cue",
    "stimintensity"), dv)

mean_outcome <- subjectwise[1:(length(subjectwise) - 1)]
wide <- mean_outcome %>%
    tidyr::spread(cue, mean_per_sub)
wide$stim_name <- NA
wide$diff <- wide$high_cue - wide$low_cue
wide$stim_name[wide$stimintensity == "high_stim"] <- "high"
wide$stim_name[wide$stimintensity == "med_stim"] <- "med"
wide$stim_name[wide$stimintensity == "low_stim"] <- "low"
wide$stim_ordered <- factor(wide$stim_name,
    levels = c("low", "med", "high")
)


subjectwise_diff <- meanSummary(wide, c("subject"), "diff")
# subjectwise_diff$stim_ordered <- factor(subjectwise_diff$stim_ordered,
#     levels = c("low", "med", "high")
# )
subjectwise_NA <- subjectwise_diff %>% filter(!is.na(sd))
groupwise_diff <- summarySE(
    data = subjectwise_NA,
    measurevar = "mean_per_sub", # variable created from above
    #withinvars = c("stim_ordered"), # iv
    #idvar = "subject"
)

# per stim _____________________________________________________________________
# subjectwise_diff <- meanSummary(wide, c("subject", "stim_ordered"), "diff")
# subjectwise_diff$stim_ordered <- factor(subjectwise_diff$stim_ordered,
#     levels = c("low", "med", "high")
# )
# subjectwise_NA <- subjectwise_diff %>% filter(!is.na(sd)) 
# groupwise_diff <- summarySEwithin(
#     data = subjectwise_NA,
#     measurevar = "mean_per_sub", # variable created from above
#     withinvars = c("stim_ordered"), # iv
#     idvar = "subject"
# )
cue.iqr <- df.centered_NA %>%
  group_by(subject, cue) %>%
  summarize(IQR = IQR(OUTCOME, na.rm = TRUE)) %>%
  arrange(IQR)
## `summarise()` has grouped output by 'subject'. You can override using the
## `.groups` argument.
model.iqr <- lmer(IQR ~ cue + (1|subject), data = cue.iqr)
summary(model.iqr)
## Linear mixed model fit by REML. t-tests use Satterthwaite's method [
## lmerModLmerTest]
## Formula: IQR ~ cue + (1 | subject)
##    Data: cue.iqr
## 
## REML criterion at convergence: 1794.4
## 
## Scaled residuals: 
##     Min      1Q  Median      3Q     Max 
## -2.0326 -0.5190 -0.1210  0.4566  2.6943 
## 
## Random effects:
##  Groups   Name        Variance Std.Dev.
##  subject  (Intercept) 165.60   12.87   
##  Residual              66.75    8.17   
## Number of obs: 227, groups:  subject, 114
## 
## Fixed effects:
##             Estimate Std. Error      df t value Pr(>|t|)    
## (Intercept)   29.550      1.431 149.757  20.654   <2e-16 ***
## cuelow_cue     0.831      1.086 111.517   0.765    0.446    
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Correlation of Fixed Effects:
##            (Intr)
## cuelow_cue -0.382

our design is conflated with variability and the placebo effect, because the high cues have more variability. but actually no! IQR does not differ as a function of cue leve. There’s more to it!

expect.iqr <- df.centered_NA %>%
  group_by(subject) %>%
  summarize(IQR = IQR(EXPECT, na.rm = TRUE)) %>%
  arrange(IQR)

colnames(expect.iqr)
## [1] "subject" "IQR"
colnames(subjectwise_NA)
## [1] "subject"      "mean_per_sub" "sd"
merge_cueeffect_IQR <- merge(subjectwise_NA, expect.iqr, by = "subject")
head(merge_cueeffect_IQR)
##   subject mean_per_sub        sd       IQR
## 1      10    10.267275 14.728124 45.927555
## 2     100     5.513644 10.175649 23.331188
## 3     101     8.155616 21.706200 38.016011
## 4     103    -4.610429  9.444593  9.118222
## 5     104     6.278523 18.905402 36.252133
## 6     105     4.393742 13.162857 24.395731
range(merge_cueeffect_IQR$mean_per_sub)
## [1] -35.99724  37.83760
range(merge_cueeffect_IQR$IQR)
## [1]   6.940743 109.358498
g<- cueR::plot_ggplot_correlation(data = merge_cueeffect_IQR, 
                              x = 'mean_per_sub', y = 'IQR', 
                                    p_acc = 0.001, r_acc = 0.01, 
                                    limit_min = -40, limit_max = 200, label_position = .6)
g + xlab("cue effect (high vs. low cue OUTCOME)") + ylab("EXPECT IQR") + ylim(0,150) + xlim(-50, 50)
## Scale for y is already present.
## Adding another scale for y, which will replace the existing scale.
## Scale for x is already present.
## Adding another scale for x, which will replace the existing scale.

pretty obvious now that i think about it. those with larger cue effects wil have larger IQRs. in order for one to have a cue effect, you do need to report your outcome ratings drastically different depending on the cue presented.

8.4 Here I plot the expectation rating distribution, BUT sorted based on one’s cue effect difference

merge_df_cue <- merge(subjectwise_NA, df.centered_NA, by = "subject")
head(merge_df_cue)
##   subject mean_per_sub       sd src_subject_id session_id param_task_name
## 1      10     10.26727 14.72812             10          4            pain
## 2      10     10.26727 14.72812             10          1            pain
## 3      10     10.26727 14.72812             10          3            pain
## 4      10     10.26727 14.72812             10          4            pain
## 5      10     10.26727 14.72812             10          4            pain
## 6      10     10.26727 14.72812             10          4            pain
##   param_run_num param_counterbalance_ver param_counterbalance_block_num
## 1             2                        4                              2
## 2             6                        4                              1
## 3             3                        4                              1
## 4             2                        4                              2
## 5             2                        4                              2
## 6             2                        4                              2
##   param_cue_type param_stimulus_type param_cond_type param_trigger_onset
## 1        low_cue            med_stim               2          1616614186
## 2        low_cue            low_stim               1          1615231970
## 3       high_cue           high_stim               6          1616008227
## 4        low_cue            med_stim               2          1616614186
## 5       high_cue            low_stim               4          1616614186
## 6       high_cue            low_stim               4          1616614186
##   param_start_biopac  ITI_onset ITI_biopac ITI_duration event01_cue_onset
## 1         1616614186 1616614549 1616614549    3.5644388        1616614553
## 2         1615231970 1615232215 1615232215    0.6961169        1615232216
## 3         1616008227 1616008469 1616008469    2.1638486        1616008471
## 4         1616614186 1616614225 1616614225    0.9021652        1616614226
## 5         1616614186 1616614480 1616614480    3.8734350        1616614484
## 6         1616614186 1616614521 1616614521    0.8413310        1616614522
##   event01_cue_biopac event01_cue_type event01_cue_filename ISI01_onset
## 1         1616614553          low_cue             l007.png  1616614554
## 2         1615232216          low_cue             l039.png  1615232217
## 3         1616008471         high_cue             h003.png  1616008472
## 4         1616614226          low_cue             l003.png  1616614227
## 5         1616614484         high_cue             h028.png  1616614485
## 6         1616614522         high_cue             h009.png  1616614523
##   ISI01_biopac ISI01_duration event02_expect_displayonset event02_expect_biopac
## 1   1616614554      0.8951526                  1616614555            1616614555
## 2   1615232217      2.0953798                  1615232219            1615232219
## 3   1616008472      1.9952071                  1616008474            1616008474
## 4   1616614227      1.9835362                  1616614229            1616614229
## 5   1616614485      1.7873995                  1616614487            1616614487
## 6   1616614523      1.8900447                  1616614525            1616614525
##   event02_expect_responseonset event02_expect_RT event02_expect_angle
## 1                   1616614556          1.617795             2.070031
## 2                   1615232220          1.518819            36.869898
## 3                   1616008477          3.368093            55.799516
## 4                   1616614232          3.089105            40.451958
## 5                   1616614490          2.976417            99.462322
## 6                   1616614527          2.601101            71.417000
##   event02_expect_angle_label ISI02_onset ISI02_biopac ISI02_duration
## 1                        FIX  1616614559   1616614559      7.5599790
## 2                        FIX  1615232223   1615232223      4.5597293
## 3                        FIX  1616008478   1616008478      0.6596248
## 4                        FIX  1616614233   1616614233      0.5646281
## 5                        FIX  1616614491   1616614491     14.6685627
## 6                        FIX  1616614529   1616614529      0.7711728
##   event03_stimulus_type event03_stimulus_displayonset event03_stimulus_biopac
## 1              med_stim                    1616614566              1616614566
## 2              low_stim                    1615232228              1615232228
## 3             high_stim                    1616008479              1616008479
## 4              med_stim                    1616614234              1616614234
## 5              low_stim                    1616614506              1616614506
## 6              low_stim                    1616614529              1616614529
##   event03_stimulus_C_stim_match event03_stimulusC_response
## 1                            NA                          0
## 2                            NA                          0
## 3                            NA                          0
## 4                            NA                          0
## 5                            NA                          0
## 6                            NA                          0
##   event03_stimulusC_responsekeyname event03_stimulusC_reseponseonset
## 1                                NA                                0
## 2                                NA                                0
## 3                                NA                                0
## 4                                NA                                0
## 5                                NA                                0
## 6                                NA                                0
##   event03_stimulusC_RT ISI03_onset ISI03_biopac ISI03_duration
## 1                    0  1616614575   1616614575       4.987133
## 2                    0  1615232237   1615232237       4.287938
## 3                    0  1616008488   1616008488       1.989352
## 4                    0  1616614243   1616614243       6.494392
## 5                    0  1616614515   1616614515       2.193067
## 6                    0  1616614538   1616614538       6.684188
##   event04_actual_displayonset event04_actual_biopac
## 1                  1616614580            1616614580
## 2                  1615232241            1615232241
## 3                  1616008490            1616008490
## 4                  1616614249            1616614249
## 5                  1616614517            1616614517
## 6                  1616614545            1616614545
##   event04_actual_responseonset event04_actual_RT event04_actual_angle
## 1                   1616614583          2.508353            33.562744
## 2                   1615232244          2.684495            13.253716
## 3                   1616008493          3.525335            69.957683
## 4                   1616614252          2.417763            28.316355
## 5                   1616614519          1.984204             9.954607
## 6                   1616614548          2.704694            20.609693
##   event04_actual_angle_label param_end_instruct_onset param_end_biopac
## 1                        FIX               1616614584       1616614584
## 2                        FIX               1615232368       1615232368
## 3                        FIX               1616008626       1616008626
## 4                        FIX               1616614584       1616614584
## 5                        FIX               1616614584       1616614584
## 6                        FIX               1616614584       1616614584
##   param_experiment_duration                        event03_stimulus_P_trigger
## 1                  398.5102 Command Recieved: TRIGGER_AND_Response: RESULT_OK
## 2                  398.1037 Command Recieved: TRIGGER_AND_Response: RESULT_OK
## 3                  399.0270 Command Recieved: TRIGGER_AND_Response: RESULT_OK
## 4                  398.5102 Command Recieved: TRIGGER_AND_Response: RESULT_OK
## 5                  398.5102 Command Recieved: TRIGGER_AND_Response: RESULT_OK
## 6                  398.5102 Command Recieved: TRIGGER_AND_Response: RESULT_OK
##   event03_stimulus_P_delay_between_medoc event03_stimulus_V_patientid
## 1                                      0                           NA
## 2                                      0                           NA
## 3                                      0                           NA
## 4                                      0                           NA
## 5                                      0                           NA
## 6                                      0                           NA
##   event03_stimulus_V_filename event03_stimulus_C_stim_num
## 1                          NA                           0
## 2                          NA                           0
## 3                          NA                           0
## 4                          NA                           0
## 5                          NA                           0
## 6                          NA                           0
##   event03_stimulus_C_stim_filename delay_between_medoc ses run runtype      cue
## 1                               NA          0.05064011   4   2    pain  low_cue
## 2                               NA          0.05586195   1   6    pain  low_cue
## 3                               NA          0.04395199   3   3    pain high_cue
## 4                               NA          0.08373189   4   2    pain  low_cue
## 5                               NA          0.06575012   4   2    pain high_cue
## 6                               NA          0.04667401   4   2    pain high_cue
##   stimintensity   OUTCOME    EXPECT OUTCOME_cm OUTCOME_demean EXPECT_cm
## 1      med_stim 33.562744  2.070031   40.66489      -7.102146  42.56259
## 2      low_stim 13.253716 36.869898   40.66489     -27.411174  42.56259
## 3     high_stim 69.957683 55.799516   40.66489      29.292793  42.56259
## 4      med_stim 28.316355 40.451958   40.66489     -12.348535  42.56259
## 5      low_stim  9.954607 99.462322   40.66489     -30.710283  42.56259
## 6      low_stim 20.609693 71.417000   40.66489     -20.055197  42.56259
##   EXPECT_demean OUTCOME_zscore EXPECT_zscore trial_index lag.OUTCOME_demean
## 1    -40.492556     -0.3268431   -1.40964500          12          -20.05520
## 2     -5.692689     -1.2614711   -0.19817644           9           43.30186
## 3     13.236929      1.3480638    0.46080992           8          -19.97422
## 4     -2.110629     -0.5682836   -0.07347616           2          -28.36097
## 5     56.899736     -1.4132971    1.98081910          10           46.57600
## 6     28.854414     -0.9229466    1.00449278          11          -30.71028
##   EXPECT_cmc OUTCOME_cmc run_order
## 1  -18.68492   -23.95299         b
## 2  -18.68492   -23.95299         a
## 3  -18.68492   -23.95299         b
## 4  -18.68492   -23.95299         b
## 5  -18.68492   -23.95299         b
## 6  -18.68492   -23.95299         b
# validate _____________________________________________________________________
# sorted_data <- merge_df_cue %>%
#   group_by(subject) %>%
#   arrange(mean_per_sub)

# Reorder the "subject" factor based on the sorted order
g <- ggplot(merge_df_cue, aes(x = reorder(subject, mean_per_sub), y = EXPECT, fill = subject)) +
  geom_boxplot(outlier.shape = NA, width = 1.2, position = position_dodge(2)) +  
  geom_jitter(width = .1, alpha = 0, size = 1) +
  labs(x = "Subject (sorted based on Cue effect size (High vs. Low Outcome rating)", y = "Pain Expect Rating") +
  theme_classic() +
  theme(legend.position = "none") +
  scale_x_discrete(breaks = NULL) 

# Convert ggplot object to a plotly object with hover information
g_plotly <- ggplotly(ggplot_largetext(g), tooltip = c("x", "y"))
## Warning: `position_dodge()` requires non-overlapping x intervals
## Warning: Aspect ratios aren't yet implemented, but you can manually set a
## suitable height/width

## Warning: Aspect ratios aren't yet implemented, but you can manually set a
## suitable height/width
g_plotly

8.5 those who use the scale widely will have greater cue effects, simply because they use the scale widely!

But that doesn’t necessarily indicate that their expectation and cue correlations should be high Those with grater scale use, also susceiptible to cues? wider IQR -> greater correlation with expectation and outcome ratings? > The more wider the scale you use, the more likely your expectation and outcome ratings are corerlated this makes sense, because if you have anchoring bias, your expectation will follow the cue, and thereby the scale might be wider? compared to those who ignore the cue? I’m not sure.

# expect.iqr <- df.centered_NA %>%
#   group_by(subject) %>%
#   summarize(IQR = IQR(EXPECT, na.rm = TRUE)) %>%
#   arrange(IQR)
head(df.centered_NA)
## # A tibble: 6 × 76
##   src_subject_id session_id param_task_name param_run_num param_counterbalance…¹
##            <int>      <int> <chr>                   <int>                  <int>
## 1              2          1 pain                        1                      3
## 2              2          1 pain                        1                      3
## 3              2          1 pain                        1                      3
## 4              2          1 pain                        1                      3
## 5              2          1 pain                        1                      3
## 6              2          1 pain                        1                      3
## # ℹ abbreviated name: ¹​param_counterbalance_ver
## # ℹ 71 more variables: param_counterbalance_block_num <int>,
## #   param_cue_type <chr>, param_stimulus_type <chr>, param_cond_type <int>,
## #   param_trigger_onset <dbl>, param_start_biopac <dbl>, ITI_onset <dbl>,
## #   ITI_biopac <dbl>, ITI_duration <dbl>, event01_cue_onset <dbl>,
## #   event01_cue_biopac <dbl>, event01_cue_type <chr>,
## #   event01_cue_filename <chr>, ISI01_onset <dbl>, ISI01_biopac <dbl>, …
corr_n_iqr <- df.centered_NA %>%
  dplyr::group_by(subject) %>%
  dplyr::summarise(
    correlation = cor(EXPECT, OUTCOME, use = "complete.obs"),
    IQR = IQR(EXPECT, na.rm = TRUE)
  )

ggplot(corr_n_iqr, aes(x = correlation, y = IQR)) +
  geom_point() +  # This adds the scatter plot points
  theme_classic() +  # Optional: Adds a minimal theme to the plot
  # coord_fixed(aspect.ratio = 1) +
  labs(
    title = "Scatter Plot of Correlation vs. IQR",
    x = "Correlation",
    y = "IQR"
  )
## Warning: Removed 1 rows containing missing values (`geom_point()`).
cueR::plot_ggplot_correlation(data = corr_n_iqr, x = 'correlation', y = 'IQR',
                                    p_acc = 0.001, r_acc = 0.01,
                                    limit_min = -40, limit_max = 200, label_position = .6)
## Warning: Removed 1 rows containing non-finite values (`stat_cor()`).
## Removed 1 rows containing missing values (`geom_point()`).

8.5.1 Sort based on IQR

sorted_data <- df.centered_NA %>%
  group_by(subject) %>%
  summarize(IQR = IQR(OUTCOME, na.rm = TRUE)) %>%
  arrange(IQR)
# Reorder the "subject" factor based on the sorted order
df.centered_NA$subject <- factor(df.centered_NA$subject, levels = sorted_data$subject)

# Create the ggplot
g <- ggplot(df.centered_NA, aes(x = subject, y = OUTCOME, fill = subject)) +
  geom_boxplot(outlier.shape = NA, width = 1.2, position = position_dodge(2)) +  
  geom_jitter(width = .1, alpha = 0, size = 1) +
  labs(x = "Subject", y = "Pain Outcome Rating") +
  theme_classic() +
  theme(legend.position = "none") +
  scale_x_discrete(breaks = NULL) 

# Convert ggplot object to a plotly object with hover information
g_plotly <- ggplotly(ggplot_largetext(g), tooltip = c("x", "y"))
## Warning: `position_dodge()` requires non-overlapping x intervals
## Warning: Aspect ratios aren't yet implemented, but you can manually set a
## suitable height/width

## Warning: Aspect ratios aren't yet implemented, but you can manually set a
## suitable height/width
g_plotly