【问题标题】:Trouble splitting up data evenly?难以均匀拆分数据?
【发布时间】:2015-03-15 01:49:31
【问题描述】:

我试图在 R 中均匀地拆分数据。例如,我正在使用 R Studio 中内置的数据集汽车,有 50 行。如果我想将数据分成两部分,我会按照以下方式做一些事情: cars$split <- rep(1:2, each=25) 我将在其中创建一个名为 split 的列,并将前 25 个值分配给 1,将接下来的 25 个值分配给 2。但是,如果我想将数据拆分为 8 个部分(基于由用户自行决定),我将无法平均划分 50 / 8,因为它等于 6.25。在这种情况下,我只需使用上面的函数将最后两行(因为 50 / 8 = 6.25 和 6 * 8 = 48 所以我们将剩下 2 行)分配给数字 8。但是,我无法做到这一点,因为 rep 函数需要正确划分,所以我尝试写出一些逻辑,但我遇到了一个问题:

Error in `$<-.data.frame`(`*tmp*`, "split", value = c(1L, 1L, 1L, 1L,  : replacement has 48 rows, data has 50 

关于如何解决这个问题的任何想法?我的尝试如下所示:

numDataPerSection <- floor(nrow(cars) / userInputNum)
if(nrow(cars) %% userInputNum != 0){
  #If not divisible, assign last few data points to the last number
  cars$split <- rep(1:ncls, each=numDataPerSection, len = nrow(cars) - (nrow(cars) %% userInputNum))
  for(i in nrow(cars) %% userInputNum){
    cars$split[nrow(cars) - i] <- userInputNum 
  }
}
#Everything divides correctly
else{
  cars$split <- rep(1:ncls, each=numDataPerSection)
}

【问题讨论】:

  • findInterval(1:50, seq(0, 50, by=7))
  • @Khashaa 这很好用,但是剩下的值呢?在您的示例中,最后一行(第 50 行)将等于 8。我将如何得到它以使其等于 7?

标签: r split dataframe rep


【解决方案1】:

使用这样的函数来创建索引怎么样?

create.indices <- function(nrows, sections) {
  indices <- rep(1:sections,each=floor(nrows/sections))
  indices <- append(indices, rep(tail(indices, 1), nrows%%sections))
  return(indices)
}

create.indices(50,8)
# [1] 1 1 1 1 1 1 2 2 2 2 2 2 3 3 3 3 3 3 4 4 4 4 4 4 5 5 5 5 5 5 6 6 6 6 6 6 7 7 7 7 7 7 8 8 8 8 8 8 8 8

【讨论】:

    【解决方案2】:

    你可以使用类似的东西

    split1 <- function(n,s){ c( rep(1:s, each=n%/%s), rep(s, n%%s) ) } 
    cars$split <- split1(nrow(cars,userInputNum))
    

    但这不是很平衡,因为在您的示例中,类别 8 比任何其他类别都大两个,并且 55 行和 8 个部分会更糟:

    > split1(50,8)
     [1] 1 1 1 1 1 1 2 2 2 2 2 2 3 3 3 3 3 3 4 4 4 4 4 4 5 5 5 5 5 5 6 6 6 6 6 6 7 7
    [39] 7 7 7 7 8 8 8 8 8 8 8 8
    > table(split1(50,8))
    1 2 3 4 5 6 7 8 
    6 6 6 6 6 6 6 8
    > table(split1(55,8))
     1  2  3  4  5  6  7  8 
     6  6  6  6  6  6  6 13 
    

    你可以用类似的东西做得更好

    split2 <- function(n,s){ ((1:n)*s+n-s) %/% n }
    

    产生

    > split2(50,8)
     [1] 1 1 1 1 1 1 1 2 2 2 2 2 2 3 3 3 3 3 3 4 4 4 4 4 4 5 5 5 5 5 5 5 6 6 6 6 6 6
    [39] 7 7 7 7 7 7 8 8 8 8 8 8
    > table(split2(50,8))
    1 2 3 4 5 6 7 8 
    7 6 6 6 7 6 6 6 
    > table(split2(55,8))
    1 2 3 4 5 6 7 8 
    7 7 7 7 7 7 7 6 
    

    【讨论】:

      【解决方案3】:

      您可以使用rep()length.out 参数来创建您的split 列:rep(1:8, length.out = 50, each = round(50/8))。使用round() 函数可以很好地实现组大小的均匀分布:

      > table(rep(1:8, length.out = 50, each = round(50/8)))
      
      1 2 3 4 5 6 7 8 
      8 6 6 6 6 6 6 6 
      

      【讨论】:

        猜你喜欢
        • 2019-10-05
        • 1970-01-01
        • 1970-01-01
        • 2013-05-27
        • 1970-01-01
        • 2011-07-16
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多