我想在R中创建一个训练计划,通过从大型数据框中包含的训练生成一系列训练(行是训练,3列包含锻炼名称,类别和持续时间的功能)。 '分类'取值A到N,每个类别的训练次数不等。我想按顺序生成序列如下: 1.从A类中抽取随机训练,然后从B,然后从C到N,开始序列。 2.通过重复(1)继续生成序列,每次绘制而不从A类到N类替换。 3.当绘制任何类别(例如A)的所有训练时,重新填充'该类别并开始绘图而无需再次更换。 4.继续,直到所有锻炼至少使用一次。 5.输出构建的序列,但保留每个训练的所有原始信息(即所有3列)(包括重复)。
感谢您对这个非常重要的问题的帮助:)
感谢Jim,您的样本数据集和您的回复。这是一个很好的代表性假数据集(为简单起见,实际类别少于实际):
set.seed(1)
dat <- data.frame(workout = sample(1:200), category = sample(c('A','B','C'),200,T))
head(dat)
# workout category
# 1 25 C
# 2 14 C
# 3 191 C
# 4 88 C
# 5 73 B
# 6 34 B
但是,我应该指定我每天只需要一次锻炼,因此每个输出行代表锻炼计划中的一天。希望输出看起来像这样:
head(dat)
#Day workout category
#1 8 A
#2 73 B
#3 88 C
#4 4 A
答案 0 :(得分:1)
dat <- data.frame(workout = sample(1:15), category = sample(c('A','B','C'),15,T))
dat
# workout category
#1 14 A
#2 1 B
#3 11 A
#4 9 B
#5 13 A
#6 12 C
#7 6 B
#8 8 C
#9 3 C
#10 15 A
#11 4 C
#12 7 B
#13 5 A
#14 10 A
#15 2 B
cats <- list()
cats[[1]] <- which(dat$category=='A')
cats[[2]] <- which(dat$category=='B')
cats[[3]] <- which(dat$category=='C')
lens <- sapply(cats,length)
m <- max(lens)
days <- matrix(0,m,3)
for(i in 1:3){
if(lens[i]==m) days[,i] <- sample(cats[[i]])
else days[,i] <- c(sample(cats[[i]]),sample(cats[[i]],m-lens[i]))
}
然后适当重新排序的数据集是
dat[c(t(days)),]
# workout category
#13 5 A
#7 6 B
#6 12 C
#5 13 A
#2 1 B
#8 8 C
#14 10 A
#12 7 B
#11 4 C
#10 15 A
#4 9 B
#9 3 C
#1 14 A
#15 2 B
#11.1 4 C
#3 11 A
#2.1 1 B
#6.1 12 C
编辑:如果某些类别出现的次数是其他类别的两倍以上,则需要对上述内容进行一些修改,您应该使用下面的函数
reorder <- function(dat){
if(!('category' %in% names(dat))) return('No column named category')
categories <- sort(unique(dat$category))
N <- length(categories)
fun <- function(cat) which(dat$category==cat)
cats <- lapply(categories,fun)
lens <- sapply(cats,length)
m <- max(lens)
days <- matrix(0, m, N)
for(i in 1:N){
ratio <- m/lens[i]
out <- sample(cats[[i]])
if(ratio > 1){
if(ratio > 2) for(j in 2:floor(ratio)) out <- c(out, sample(cats[[i]]))
out <- c(out, sample(cats[[i]], m - length(out)))
}
days[,i] <- out
}
return(dat[c(t(days)),])
}