I'm searching for an elegant solution for combining, duplicating, and mutating rows based on a condition:
In my example, I would like to combine x = 1 and x = 2 and then duplicate these rows. Then mutate each subset back to their original classification.
Data
df <- tibble(x = c(1,1,1,2,2,2,3,4,5,6),
y = c(11,12,13,14,15,16,17,18,19,20),
z = c(21,22,23,24,25,26,27,28,29,30))
x y z
<dbl> <dbl> <dbl>
1 1 11 21
2 1 12 22
3 1 13 23
4 2 14 24
5 2 15 25
6 2 16 26
7 3 17 27
8 4 18 28
9 5 19 29
10 6 20 30
Current Solution
Combine rows when x is in 1 or 2 and store them as 1
df <- df %>%
mutate(x = ifelse(x %in% c(1,2), 1, x))
Filter for x is 1 and mutate to 2. Store this as a subset
df_temp <- df %>%
filter(x == 1) %>%
mutate(x = 2)
Bind the rows back
df <- rbind(df,df_temp)
Desired Output
x y z
<dbl> <dbl> <dbl>
1 1 11 21
2 1 12 22
3 1 13 23
4 1 14 24
5 1 15 25
6 1 16 26
7 3 17 27
8 4 18 28
9 5 19 29
10 6 20 30
11 2 11 21
12 2 12 22
13 2 13 23
14 2 14 24
15 2 15 25
16 2 16 26
I think the first step can be skipped. separate_rows() may do the trick here if i combine them with a separator but i'd like to avoid this.
Looking for a dplyr solution.
EDIT 2:
If we simplify the data above to:
df <- tibble(x = c(1,1,2,2,2,3,4,5,6),
y = c(11,12,14,15,16,17,18,19,20),
z = c(21,22,24,25,26,27,28,29,30))
Where the number of rows of x = 1 and x = 2 are different. Filtering and reversing y and z no longer gives the correct solution.
Expected outcome
x y z
<dbl> <dbl> <dbl>
1 1 11 21
2 1 12 22
3 1 14 24
4 1 15 25
5 1 16 26
6 2 14 24
7 2 15 25
8 2 16 26
9 2 11 21
10 2 12 22
11 3 17 27
12 4 18 28
13 5 19 29
14 6 20 30
you can try
df %>%
full_join(filter(df, x %in% 1:2) %>% complete(x, y))
# A tibble: 5 x 2
x y
<dbl> <dbl>
1 1 6
2 2 7
3 3 8
4 1 7
5 2 6
When including column z, one has to complete over the nested columns y & z like
df %>%
full_join(filter(df, x %in% 1:2) %>%
complete(x, nesting(y, z))) %>%
arrange(x)
# A tibble: 16 x 3
x y z
<dbl> <dbl> <dbl>
1 1 11 21
2 1 12 22
3 1 13 23
4 1 14 24
5 1 15 25
6 1 16 26
7 2 14 24
8 2 15 25
9 2 16 26
10 2 11 21
11 2 12 22
12 2 13 23
13 3 17 27
14 4 18 28
15 5 19 29
16 6 20 30
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