I have a dataframe with columns containing lists of values:
dt
onset_l coda_l
1 3, 7 7, 4, 1
3 7 7, 1, 3
12 1, 7 7, 4, 1
21 6, 7 7, 4, 1
23 7 7, 1, 5
What I want to do is create a new column, say, coda_flag, that flags whether the values in column coda_l progressively decrease or not.
I've tried this lapply method:
dt$coda_flag <- lapply(dt$coda_l, function(x) ifelse(x[1] > x[2] & x[2] > x[3], 1, 0))
The output is okay but I dislike that I have to enumerate x[1], x[2] and so on because in some cases I may not know the exact number of values in the lists.
The desired output would be:
dt
onset_l coda_l coda_flag
1 3, 7 7, 4, 1 1 # values do progressively decrease
3 7 7, 1, 3 0 # values do not progressively decrease
12 1, 7 7, 4, 1 1
21 6, 7 7, 4, 1 1
23 7 7, 1, 5 0
How can this be achieved?
Reproducible data:
dt <- structure(list(onset_l = list(c("3", "7"), "7", c("1", "7"),
c("6", "7"), "7"), coda_l = list(c("7", "4", "1"), c("7",
"1", "3"), c("7", "4", "1"), c("7", "4", "1"), c("7", "1", "5"
))), row.names = c(1L, 3L, 12L, 21L, 23L), class = "data.frame")
You can use is.unsorted() - although it can only detect increasing order so it's necessary to reverse the vector first.
dt$coda_flag <- +!sapply(dt$coda_l, function(x) is.unsorted(rev(as.numeric(x))))
onset_l coda_l coda_flag
1 3, 7 7, 4, 1 1
3 7 7, 1, 3 0
12 1, 7 7, 4, 1 1
21 6, 7 7, 4, 1 1
23 7 7, 1, 5 0
Note the strictly argument controls what happens in the event of tied values.
x <- c(1, 2, 2, 3)
is.unsorted(x)
[1] FALSE
is.unsorted(x, strictly = TRUE)
[1] TRUE
One dplyr and purrr solution could be:
dt %>%
mutate(coda_flag = map_int(.x = coda_l, ~ +(all(diff(as.numeric(.x)) < 1))))
onset_l coda_l coda_flag
1 3, 7 7, 4, 1 1
2 7 7, 1, 3 0
3 1, 7 7, 4, 1 1
4 6, 7 7, 4, 1 1
5 7 7, 1, 5 0
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With