代码之家  ›  专栏  ›  技术社区  ›  Adam Hoelscher

为R中的模拟样本按类生成ID编号

  •  1
  • Adam Hoelscher  · 技术社区  · 10 年前

    我试图用以下参数模拟覆盖多个类的群体的ID号

    • 每个类按照相同的模式顺序分配ID。
    • 每个类的ID前缀都不同于其他类的前缀。

    生成一些示例数据

    data(mtcars)
    set.seed(9999)
    mtcars$count<-sample(x = 1:100,size = 32,replace=T)
    mtcars
    Car.Sample<-sample(1:sum(mtcars$count),15)
    

    所以,我模拟了人口中的15辆汽车(1774)。关于如何计算样本中每个成员的身份证号码,我最初的想法是使用我采样的号码,并向下滚动mtcar的记录,直到计数的总和超过样本号码。然后从该记录之前的所有记录中减去计数之和,剩余的是该类内的车辆的ID号。例如

    Car.ID<-function(x){
      Commute <- 0
      Counter <- 0
      while (Commute<x){
        Counter <- Counter + 1
        Commute <- Commute + mtcars[Counter,'count']
      }
    
      # we overshot the count so we need to step back one iteration
      Commute <- Commute - mtcars[Counter,'count']
    
      Class <- rownames(mtcars)[Counter]
      ID.Num <- x - Commute
      temp <- paste(Class,ID.Num,sep=':')
      return(temp)
    }
    

    这个函数生成正确的结果,如果我输入每个可能的样本号,我会得到一个与上述规则一致的分配ID列表。问题是它比吐口水慢。我的实际用例有1000个类,我可能需要模拟10^5或10^6的样本大小。

    1. 有没有办法优化这种逻辑?
    2. 是否有更有效的逻辑来分配这些ID?

    谢谢你的帮助。

    目前最佳答案:优化使用 cumsum 函数(@pattabongo)

    mtcars$Commute <- cumsum(mtcars$count)
    Car.ID <- function(x) {
      row <- head(which(mtcars$Commute >= x), n = 1)
      Commutation <- mtcars$Commute[row-1]
      if (length(Commutation)==0) {Commutation <- 0}
      return(paste(rownames(mtcars)[row], x - Commutation, sep = ":"))
    }
    
    1 回复  |  直到 10 年前
        1
  •  1
  •   stuwest    10 年前

    一种方法是为mtcars分配一个累计和列,这样您就不必一直重新计算。

    mtcars$cumsum <- cumsum(mtcars$count)
    
    Car.ID <- function(x) {
        if (x < mtcars$cumsum[1]) {
            return(paste(rownames(mtcars)[1], x, sep = ":"))
        } else {
            row <- tail(which(mtcars$cumsum < x), n = 1)
            return(paste(rownames(mtcars)[row + 1], x - mtcars$cumsum[row], sep = ":"))
        }
    }
    
    sapply(Car.Sample, Car.ID)