Kenny
Kenny

Reputation: 361

Assign values to a new column with multiple conditions

In my previous question, I needed to create a new column according to values in another column. In that question, values in expected_result is only updated when there is a CS+ in stimulus column. What I am trying to do now is to only update the value after there is a new CS+. Expected results are as shown in figure 1. For instance, in the second CS+, the value is still 30, it is only updated to 36 in the next trial.

Figure 1

enter image description here

Example data

structure(list(subject = c("subject1", "subject1", "subject1", 
"subject1", "subject1", "subject1", "subject1", "subject1", "subject1", 
"subject2", "subject2", "subject2", "subject2", "subject2", "subject2", 
"subject2", "subject2", "subject2"), stimulus = c("CS-", "CS-", 
"CS+", "CS-", "S8", "S7", "S2", "CS+", "CS+", "CS-", "CS-", "CS+", 
"S4", "S9", "S7", "CS+", "CS+", "S8"), Per_size = c(60L, 70L, 
30L, 85L, 62L, 56L, 42L, 36L, 34L, 24L, 21L, 70L, 65L, 31L, 35L, 
79L, 79L, 34L), new_expect = c(30, 30, 30, 30, 30, 30, 30, 30, 
36, 36, 36, 36, 70, 70, 70, 70, 79, 79)), row.names = c(NA, -18L
), class = c("data.table", "data.frame"))

Solution provided by @akrun for the previous question where values are updated on the CS+ trial.

df1[stimulus == 'CS+', New := Per_size]
df1[, New  := nafill(nafill(New, type = 'locf'), type = 'nocb'), subject]

Upvotes: 1

Views: 172

Answers (1)

akrun
akrun

Reputation: 887911

Based on the expected showed, it is breaking the grouping. We could do

library(dplyr)
library(tidyr)
df1 %>%
     group_by(subject) %>%
     mutate(New = lag(case_when(stimulus == 'CS+' ~ Per_size))) %>% 
     ungroup %>% 
     fill(New, .direction = 'downup')

-ouptut

# A tibble: 18 x 5
   subject  stimulus Per_size new_expect   New
   <chr>    <chr>       <int>      <dbl> <int>
 1 subject1 CS-            60         30    30
 2 subject1 CS-            70         30    30
 3 subject1 CS+            30         30    30
 4 subject1 CS-            85         30    30
 5 subject1 S8             62         30    30
 6 subject1 S7             56         30    30
 7 subject1 S2             42         30    30
 8 subject1 CS+            36         30    30
 9 subject1 CS+            34         36    36
10 subject2 CS-            24         36    36
11 subject2 CS-            21         36    36
12 subject2 CS+            70         36    36
13 subject2 S4             65         70    70
14 subject2 S9             31         70    70
15 subject2 S7             35         70    70
16 subject2 CS+            79         70    70
17 subject2 CS+            79         79    79
18 subject2 S8             34         79    79

Or using data.table

library(data.table)
library(zoo)
df1[, New := shift(fcase(stimulus == 'CS+', Per_size)), 
   subject][, New := nafill(nafill(New, type = 'locf'), type = 'nocb')]

-ouptut

df1
     subject stimulus Per_size new_expect New
 1: subject1      CS-       60         30  30
 2: subject1      CS-       70         30  30
 3: subject1      CS+       30         30  30
 4: subject1      CS-       85         30  30
 5: subject1       S8       62         30  30
 6: subject1       S7       56         30  30
 7: subject1       S2       42         30  30
 8: subject1      CS+       36         30  30
 9: subject1      CS+       34         36  36
10: subject2      CS-       24         36  36
11: subject2      CS-       21         36  36
12: subject2      CS+       70         36  36
13: subject2       S4       65         70  70
14: subject2       S9       31         70  70
15: subject2       S7       35         70  70
16: subject2      CS+       79         70  70
17: subject2      CS+       79         79  79
18: subject2       S8       34         79  79

Upvotes: 1

Related Questions