Search code examples
rdplyrmagrittr

Conditional dataframe mutations in R with magrittr and dplyr


I would like to use the succinctness of magrittr and dplyr to copy single values between rows in a subset of columns based on the values in other columns. This is a simple example; I want to apply this idea to many columns of a large dataset with multiple conditions within a long pipe of commands.

Take the dataframe df <- data.frame(a = 1:5, b = 6:10, x = 11:15, y = 16:20):

a   b   x   y

1   6   11  16
2   7   12  17
3   8   13  18
4   9   14  19
5   10  15  20

For the row where a = 5, I would like to replace the values of x and y with those in the row where b = 7, to give:

a   b   x   y

1   6   11  16
2   7   12  17
3   8   13  18
4   9   14  19
5   10  12  17

This attempt fails:

foo <- function(x){ifelse(df$a == 5, df[df$b == 7, .(df$x)], x)}
df %<>%  mutate_each(funs(foo), x, y)

The closest I can get is:

bar <- function(x){ifelse(df$a == 5, df[df$b == 7, "x"], x)}
df %<>%  mutate_each(funs(bar), x, y)

but this is incorrect as it replaces both values with the value from x, rather than x and y respectively.

Thanks for the advice.


Solution

  • You could do it using mutate_each and replace:

    df %>% mutate_each(funs(replace(., a==5, nth(., which(b==7)))), x, y)
    

    Output:

      a  b  x  y
    1 1  6 11 16
    2 2  7 12 17
    3 3  8 13 18
    4 4  9 14 19
    5 5 10 12 17
    

    Or as per @docendodiscimus 's comment it can be shortened further to (and probably [ is also better than which):

    df %>% mutate_each(funs(replace(., a==5, .[b==7])), x, y)