【问题标题】:R Loop with conditionsR循环有条件
【发布时间】: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 组嵌套另一个循环?

对于循环的任何帮助将不胜感激!

【问题讨论】:

    标签: r loops if-statement while-loop


    【解决方案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 需要进入不同的组。
    猜你喜欢
    • 2022-12-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-10-01
    • 2019-05-05
    • 1970-01-01
    相关资源
    最近更新 更多