df <- data.frame(n = c(3, 2, 2),
survive = c(2, 1, 2),
a = c(1,1,0),
b = c(0,0,1))
How can I expand the last two columns of the data.frame above, so that each row appears the number of times specified in the column 'n'. And the second column "survive" changes into binary values 0/1 according to the value of "survive"
In other words:
n survive a b
3 2 1 0
2 1 1 0
2 2 0 1
To this
survive a b
1 1 0
1 1 0
0 1 0
1 1 0
0 1 0
1 0 1
1 0 1
Several alternative solutions:
1) Using base R:
rn <- rep(1:nrow(df), df$n)
df2 <- df[rn,]
df2$survive <- as.integer(df2$survive >= ave(rn, rn, FUN = seq_along))
which gives:
> df2[,-1]
survive a b
1: 1 1 0
2: 1 1 0
3: 0 1 0
4: 1 1 0
5: 0 1 0
6: 1 0 1
7: 1 0 1
2) Using the data.table-package:
library(data.table)
df2 <- setDT(df)[, rid := .I
][, .(survive = c(rep(1, survive), rep(0, n - survive)), a, b)
, by = rid
][, rid := NULL][]
which gives:
> df2
survive a b
1: 1 1 0
2: 1 1 0
3: 0 1 0
4: 1 1 0
5: 0 1 0
6: 1 0 1
7: 1 0 1
Or a bit shorter:
df2 <- setDT(df)[, .(survive = c(rep(1, survive), rep(0, n - survive)), a, b), by = 1:nrow(df)
][, nrow := NULL]
3) Using the dplyr-package:
library(dplyr)
df %>%
mutate(rid = row_number()) %>%
.[rep(1:nrow(df), df$n),] %>%
group_by(rid) %>%
mutate(survive = c(rep(1, unique(survive)), rep(0, unique(n) - unique(survive))) ) %>%
ungroup() %>%
select(-n, -rid)
which gives:
# A tibble: 7 × 3
survive a b
<dbl> <dbl> <dbl>
1 1 1 0
2 1 1 0
3 0 1 0
4 1 1 0
5 0 1 0
6 1 0 1
7 1 0 1
Used data:
df <- data.frame(n = c(3, 2, 2),
survive = c(2, 1, 2),
a = c(1,1,0),
b = c(0,0,1))
One solution using splitstackshape to expand rows and dplyr,
library(splitstackshape)
library(dplyr)
df %>%
mutate(new = 1) %>%
expandRows('n') %>%
group_by(grp = cumsum(c(1, diff(survive) != 0))) %>%
mutate(survive = replace(new, tail(new, n() - survive[1]), 0)) %>%
arrange(grp, desc(survive)) %>%
ungroup() %>%
select(-c(new, grp))
# A tibble: 7 × 3
# survive a b
# <dbl> <dbl> <dbl>
#1 1 1 0
#2 1 1 0
#3 0 1 0
#4 1 1 0
#5 0 1 0
#6 1 0 1
#7 1 0 1
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