I would like to use the succinctness of magrittr, dplyr and possibly purrr to split a large dataframe (with many variables of different types) by one variable x
and then apply different functions conditionally by x
to each group and row within a group to a second variable y
.
Take the dataframe df <- data.frame(a, b, x, c, d, y)
, where x
are factors ( foo
, bar
) and y
are numbers. I can do what I have described inelegantly with an unpiped workflow thus:
df$y[df$x == "foo"] %<>% subtract(min(.))
df$y[df$x == "bar"] %<>% add(max(df$y[df$x == "foo"]))
I would like to rewrite this using dplyr and add it to a long pipe for df
, but all my attempts to combine mutate
, sapply
and do
have failed; as have attempts to incorporate purrr with anonymous functions, by_slice
and dmap
.
Many thanks in advance for the advice.
This is more dplyr
than magrittr
, but I think it's also more readable. I'm a bit uncomfortable with %<>%
because it disrupts the linear structure of operations, and makes the code harder to read. So I just use %>%
here.
An example dataframe that matches your description:
df <- data.frame(a = 'a',
b = 'b',
x = c("foo", "bar") ,
c = 'c',
d = 'd',
y = 1:6)
df
a b x c d y
1 a b foo c d 1
2 a b bar c d 2
3 a b foo c d 3
4 a b bar c d 4
5 a b foo c d 5
6 a b bar c d 6
Your code:
library(dplyr)
library(magrittr)
df$y[df$x == "foo"] %<>% subtract(min(.))
df
a b x c d y
1 a b foo c d 0
2 a b bar c d 2
3 a b foo c d 2
4 a b bar c d 4
5 a b foo c d 4
6 a b bar c d 6
df$y[df$x == "bar"] %<>% add(max(df$y[df$x == "foo"]))
df
a b x c d y
1 a b foo c d 0
2 a b bar c d 6
3 a b foo c d 2
4 a b bar c d 8
5 a b foo c d 4
6 a b bar c d 10
A dplyr
solution:
df %>%
mutate(y = ifelse(x == "foo", y - min(y), y)) %>%
mutate(y = ifelse(x == "bar", y + max(y[x == 'foo']), y))
a b x c d y
1 a b foo c d 0
2 a b bar c d 6
3 a b foo c d 2
4 a b bar c d 8
5 a b foo c d 4
6 a b bar c d 10
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.