Find multiple "switching points" by comparing the answers in columns

Viewed 50

I have a data set in which subjects have made choices between A and B for 13 different B's. Below is a simplified example of what the data looks like with 54 subjects and 5 choices. (1 is A, 2 is B).

      subject choice1 choice2 choice3 choice4 choice5
1       1       1       1       1       2       2       
2       2       1       1       2       2       2       
3       3       1       2       1       2       2       
4       4       1       2       2       2       2       

I would like to find the questions in which subjects switch option A to B , i.e. for subject 1 this would be choice4.

In a previous study we did this by computing number of times the subject would choose option A and then selecting the corresponding option B form a separate matrix. See code below.

However, the difference now is that instead of choosing 1 switching point, subjects were asked the questions in a randomized order, and thus there is the possibility of having multiple switching points. For example in the table above, subject 3 switches to B at choice2 and again at choice4.

I would like to find both the first time the subject switches to option B, and the last time (before sticking with B for the rest of the choices).

sure_amounts <- matrix(nrow = 4, ncol = 13) # 4 treatments, 13 questions
sure_amounts[1, ] <- c(0, 2, 3, 3.5, 4, 4.5, 5, 5.5, 6, 6.5, 7, 8, 10)  # Option B's
sure_amounts[2, ] <- seq(2, 14, 1)
sure_amounts[3, ] <- seq(2, 14, 1)  
sure_amounts[4, ] <- seq(2, 14, 1)

b_choice <- matrix(nrow = 201, ncol = 4)
switch_choice <- matrix(nrow = 201, ncol = 4) # switching point form A to B

for(j in 1:4){    # number of treatments
  for(i in 201){   # number of subjects
    choice = NULL
    fl = data$ID == i
    k = 1 + 36*(j-1)      # 36 before going to the next treatment (due to other questions)
    
    choice = c(data[fl,k:(k+12)])
    b_choice[i,j] = length(choice[choice==1])  
    temp = b_choice[i,j]
    switch_choice[i,j] <- ifelse(temp==0, 0, sure_amounts[j, temp])
  }
}

Does anyone have any tips on how to approach this? Thanks in advance!

3 Answers

I am not sure how you want your expected output to look like but you can try to get data in long format and for each subject select rows where they switch from 1 -> 2.

library(dplyr)

df %>%
  tidyr::pivot_longer(cols = -subject) %>%
  group_by(subject) %>%
  filter(value == 2 & lag(value) == 1 | 
         value == 1 & lead(value) == 2)

#    subject name    value
#     <int> <chr>   <int>
# 1       1 choice3     1
# 2       1 choice4     2
# 3       2 choice2     1
# 4       2 choice3     2
# 5       3 choice1     1
# 6       3 choice2     2
# 7       3 choice3     1
# 8       3 choice4     2
# 9       4 choice1     1
#10       4 choice2     2

Here we can see that subject 1 moves from 1 -> 2 from choice3 -> choice4 and so on.

data

df <- structure(list(subject = 1:4, choice1 = c(1L, 1L, 1L, 1L), choice2 = c(1L, 
1L, 2L, 2L), choice3 = c(1L, 2L, 1L, 2L), choice4 = c(2L, 2L, 
2L, 2L), choice5 = c(2L, 2L, 2L, 2L)), class = "data.frame", 
row.names = c(NA, -4L))

A Base R solution:

Essentially this code only substracts a lag of the decisions and detects if the difference is not equal to zero.

Code:

lapply(as.data.frame(t(df_1)[-1,]), function(x){
  t <- x - c(x[-1], 0) # row substracted by shortened row
  z <- which(t[-length(t)] != 0) # values not equal to zero and rm last value 
  z + 1 # remove lag
})

# $`1`
# [1] 4

# $`2`
# [1] 3

# $`3`
# [1] 2 3 4

# $`4`
# [1] 2

Data:

df_1 <- read.table(text = "      subject choice1 choice2 choice3 choice4 choice5
1       1       1       1       1       2       2       
2       2       1       1       2       2       2       
3       3       1       2       1       2       2       
4       4       1       2       2       2       2 ", header = T)

An alternative approach:




library(dplyr)
library(stringr)
library(purrr)


  df %>%
  mutate(g = paste0(choice1, choice2, choice3, choice4, choice5),
         switches = as.character(map(g, ~pluck(str_locate_all(.x, "12"), 1)))) %>% 
  select(-g)
#>   subject choice1 choice2 choice3 choice4 choice5      switches
#> 1       1       1       1       1       2       2           3:4
#> 2       2       1       1       2       2       2           2:3
#> 3       3       1       2       1       2       2 c(1, 3, 2, 4)
#> 4       4       1       2       2       2       2           1:2

data

df <- structure(list(subject = 1:4, choice1 = c(1L, 1L, 1L, 1L), choice2 = c(1L, 
                                                                             1L, 2L, 2L), choice3 = c(1L, 2L, 1L, 2L), choice4 = c(2L, 2L, 
                                                                                                                                   2L, 2L), choice5 = c(2L, 2L, 2L, 2L)), class = "data.frame", row.names = c("1", 
                                                                                                                                                                                                              "2", "3", "4"))

Created on 2020-07-10 by the reprex package (v0.3.0)

Related