R循环有条件
Posted
技术标签:
【中文标题】R循环有条件【英文标题】:R Loop with conditions 【发布时间】:2016-03-19 05:07:36 【问题描述】:我有一系列重复的 ID,我想将它们分配给具有固定大小的组。主题 ID 以不同的频率重复,例如:
# Example Data
ID = c(101,102,103,104)
Repeats = c(2,3,1,3)
Data = data.frame(ID,Repeats)
> head(Data)
ID Repeats
1 101 2
2 102 3
3 103 1
4 104 3
我希望相同的重复 ID 留在同一组中。但是,每个组都有固定的容量(比如只有 3 个)。例如,在我想要的输出矩阵中,每组只能容纳 3 个 ID:
# Create empty data frame for group annotation
# Add 3 rows in order to have more space for IDs
# Some groups will have NAs due to keeping IDs together (I'm OK with that)
Target = data.frame(matrix(NA,nrow=(sum(Data$Repeats)+3),
ncol=dim(Data)[2]))
names(Target)<-c("ID","Group")
Target$Group<-rep(1:3)
Target$Group<-sort(Target$Group)
> head(Target)
ID Group
1 NA 1
2 NA 1
3 NA 1
4 NA 1
5 NA 2
6 NA 2
我可以将每个 ID 循环到我的目标数据框,但这并不能保证重复的 ID 将保持在同一组中:
# Loop repeated IDs the groups
IDs.repeat = rep(Data$ID, times=Data$Repeats)
# loop IDs to Targets to assign IDs to groups
for (i in 1:length(IDs.repeat))
Target$ID[i]<-IDs.repeat[i]
在上面循环的示例中,我在两个不同的组(1 和 2)中获得了相同的 ID (102),我想避免这种情况!:
> head(Target)
ID Group
1 101 1
2 101 1
3 102 1
4 102 1
5 102 2
6 103 2
相反,如果该组中没有该 ID 的空间,我希望输出查看放置 NA 的代码。
> head(Target)
ID Group
1 101 1
2 101 1
3 NA 1
4 NA 1
5 102 2
6 102 2
如果在分配 ID i 后有足够的空间,任何人都有解决方案让 ID 留在同一组中?
我认为我需要一个循环并计算该组中的 NAs,并查看 NAs>= 是否为该唯一 ID 的长度。但是,我不知道如何同时实现这一点。也许为 j 组嵌套另一个循环?
对于循环的任何帮助将不胜感激!
【问题讨论】:
【参考方案1】:这是一种解决方案,
## This is the data.frame I'll try to match
target <- data.frame(
ID = c(
rep(101, 2),
rep(102, 3),
rep(103, 1),
rep(104, 3)),
Group = c(
rep(1L, 6), # "L", like 1L makes it an int type rather than numeric
rep(2L, 3)
)
)
print(target)
## Your example data
ID = c(101,102,103,104)
Repeats = c(2,3,1,3)
Data = data.frame(ID,Repeats)
head(Data)
ids_to_group <- 3 # the number of ids per group is specified here.
Data$Group <- sort(
rep(1:ceiling(length(Data$ID) / ids_to_group),
ids_to_group))[1:length(Data$ID)]
# The do.call(rbind, lapply(x = a series, FUN = function(x) ))
# pattern is a really useful way to stack data.frames
# lapply is basically a fancy for-loop check it out by sending
# ?lapply to the console (to view the help page).
output <- do.call(
rbind,
lapply(unique(Data$ID), FUN = function(ids)
print(paste(ids, "done.")) # I like to put print statements to follow along
obs <- Data[Data$ID == ids, ]
data.frame(ID = rep(obs$ID, obs$Repeats))
)
)
output <- merge(output, Data[,c("ID", "Group")], by = "ID")
identical(target, output) # returns true if they're equivalent
# For example inspect each with:
str(target)
str(output)
【讨论】:
感谢您的建议。这种方法很有趣,可能是一个解决方案。但是,在您的示例中,每个组的对象输出分组超过 3 个 ID(来自您上面的代码):> print(output) ID Group 1 101 1 2 101 1 3 102 1 4 102 1 5 102 1 6 103 1 7 104 2 8 104 2 9 104 2
嗯,我可能误会了。您打印的输出显示 id 101、102 和 103 标记为组 1,以及 104(第四个唯一 id)开始组 2。四个 id,每组中最多三个产生两个组。
感谢您的跟进。这正是我想要避免的。我不想在不同的组中使用相同的 ID。我希望每个 ID 都在一个组中。但是,这很困难,因为每个 ID 重复的次数不同。如果您在示例中打印(输出),您可以看到第 1 组中有 6 个 ID。如果 ID 长于可用组数,我可以使用 NA。
啊,现在我明白了。这应该可以通过将ids_to_group <- 3
更改为ids_to_group <- 1
来实现。
谢谢!尽管该代码将每个 ID 分配给一个组。我可以每组有不同的 ID(我实际上需要每组混合 ID)但是,我在每组的位置数量上受到限制(即每组 4 个位置)并且 ID 的数量不同。所以在我上面的例子中,101 适合第 1 组,只留下两个空位,因此 3 次重复的 102 需要进入不同的组。以上是关于R循环有条件的主要内容,如果未能解决你的问题,请参考以下文章
R语言使用Repeat函数多次执行代码块内的语句,实现循环执行任务的功能:repeat没有提供任何检查条件,所以编码者必须给出退出重复循环的条件(一般使用if和break)