mauna
mauna

Reputation: 1118

How to mutate a column given a dataframe that has the conditions?

I have a two-column data frame. The first column is a timestamp and the second column is some value. For example:

library(tidyverse)
set.seed(123)
data_df <- tibble(t = 1:15,
                  value = sample(letters, 15))

I have a another data frame that specifies the range of timestamps that need to be updated and their corresponding values. For example:

criteria_df <- tibble(start = c(1, 3, 7),
                      end = c(2, 5, 10),
                      value = c('a', 'b', 'c')
                      )

This means that I need to mutate the value column in data_df so that its value from t=1 to t=2 is 'a', from t=3 to t=5 is 'b' and from t=7 to t=10 is 'c'.

What is the recommended way to do this in R?

The only way I could think of is to loop each row in criteria_df and mutate the value column in data_df after filtering the t column, like so:

library(iterators)
library(foreach)

foreach(row = row_iter, .combine = c) %do% {
  seg_start = row$start
  seg_end = row$end
  new_value = row$value

  data_df %<>%
    mutate(value = if_else(between(t, seg_start, seg_end),
                                    new_value,
                                    value))
  NULL
}

Upvotes: 0

Views: 150

Answers (1)

Ronak Shah
Ronak Shah

Reputation: 389215

We can do a two-step base R solution, where we first find the values which lies in the range of criteria_df start and end and then replace the data_df value from it's equivalent criteria_df's value if it matches or keep it as it is.

inds <- sapply(data_df$t, function(x) criteria_df$value[x >= criteria_df$start 
                                                      & x <= criteria_df$end])

data_df$value <- unlist(ifelse(lengths(inds) > 0, inds, data_df$value))
data_df

#      t value
#   <int> <chr>
# 1     1 a    
# 2     2 a    
# 3     3 b    
# 4     4 b    
# 5     5 b    
# 6     6 a    
# 7     7 c    
# 8     8 c    
# 9     9 c    
#10    10 c    
#11    11 p    
#12    12 g    
#13    13 r    
#14    14 s    
#15    15 b    

Upvotes: 2

Related Questions