I have seen this question before: R adding a new column in a data frame by recursivly filling 1:3 value based on another column
my question is probably the same, but my case is a little different
Let's say I want to fill a new column based on the below number range:
Group Range
1 A 2-4
2 B 6-8
3 C 10-12
the data frame:
df <- data.frame(Group = rep(c("A", "B", "C"), times = c(2, 4, 6))
> df
Group
1 A
2 A
3 B
4 B
5 B
6 B
7 C
8 C
9 C
10 C
11 C
12 C
My case is I want to add a new column Type
by recursively filling based on the range column.
The resulting DF is like this:
> df2
Group Type
1 A 2
2 A 3
3 B 6
4 B 7
5 B 8
6 B 6
7 C 10
8 C 11
9 C 12
10 C 10
11 C 11
12 C 12
I tried to use mutate like below:
df <- df %>% group_by(Group) %>%
mutate(Type = if_else(Group == "A",rep_len(2:4, length.out = 2), 0), .after = Group)
df
but it still doesn't work
what is the correct script for this case, especially if there is additional data in the Group column?
Thank you for the help
CodePudding user response:
Using mapply
and strsplit
it can be done
df1:
Group Range
1 A 2-4
2 B 6-8
3 C 10-12
df2$Type <- unlist(mapply(\(x,y){
a <- as.numeric(y)
rep(seq(a[1], a[2]), length = x)
}, c(2,4,6), strsplit(df1$Range, "-")))
Group Type
1 A 2
2 A 3
3 B 6
4 B 7
5 B 8
6 B 6
7 C 10
8 C 11
9 C 12
10 C 10
11 C 11
12 C 12
CodePudding user response:
How do you like this way.
For another dataset, just modify df and df1.
df <- data.frame(Group = rep(c("A", "B", "C"), times = c(2, 4, 6)))
(df1 <- data.frame(Group = c("A","B","C"), Range = c("2-4","6-8","10-12")))
# Group Range
# 1 A 2-4
# 2 B 6-8
# 3 C 10-12
res <- c()
for(i in 1:nrow(df1)){
r <- strsplit(df1[i,]$Range, "-")[[1]]
type <- r[1]:r[2]
times <- length(df[df[1]==df1[i,]$Group])
rep <- rep(type, as.integer(times/length(type)) 1)
res <- c(res, rep[1:times])
}
cbind(df, res)
# Group res
# 1 A 2
# 2 A 3
# 3 B 6
# 4 B 7
# 5 B 8
# 6 B 6
# 7 C 10
# 8 C 11
# 9 C 12
# 10 C 10
# 11 C 11
# 12 C 12