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(来自您上面的代码):&gt; 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 &lt;- 3 更改为ids_to_group &lt;- 1 来实现。 谢谢!尽管该代码将每个 ID 分配给一个组。我可以每组有不同的 ID(我实际上需要每组混合 ID)但是,我在每组的位置数量上受到限制(即每组 4 个位置)并且 ID 的数量不同。所以在我上面的例子中,101 适合第 1 组,只留下两个空位,因此 3 次重复的 102 需要进入不同的组。

以上是关于R循环有条件的主要内容,如果未能解决你的问题,请参考以下文章

如何避免R中特定多条件语句中的循环

while循环的条件写1代表啥意思?

错误打破了for循环:条件try语句?

R语言使用Repeat函数多次执行代码块内的语句,实现循环执行任务的功能:repeat没有提供任何检查条件,所以编码者必须给出退出重复循环的条件(一般使用if和break)

C. Yet Another Counting Problem(循环节规律)

如何用R语言for循环形成112358