【问题标题】:Split integers based on a value in second column, assign new values, and, recombine into new dataset根据第二列中的值拆分整数,分配新值,然后重新组合成新数据集
【发布时间】:2020-04-08 08:11:31
【问题描述】:

R 中,我有一个包含所有整数的2xn 数据矩阵。

第一列表示项目的大小。其中一些大小是由于合并造成的,因此第二列表示进入该大小的项目数(包括 1 个)(称为“索引”)。索引的总和表示原始数据中有多少项。

我现在需要创建一个新数据集,该数据集根据索引中的数字将任何合并的大小拆分回来,从而产生一个 2xn 向量(根据索引的总数具有新的长度 n)第二列全为 1。

我需要这种分裂以两种方式发生。

  • “均匀地”,其中任何合​​并的大小都尽可能均匀地分配给索引的数量。例如,6 的大小和3 的索引现在将是c(2,2,2)重要的是,所有数字都必须是整数,所以它应该是 c(1,2) 或 c(2,1) 之类的东西。不能是 c(1.5,1.5)。
  • “异构”,其中大小数量倾斜以将1 分配给索引中的所有位置,除了一个包含提醒的位置。例如,大小为 6 且索引为 3,现在将是 c(1,1,4) 或 1、1 和 4 的任意组合。

下面我提供了一些示例数据,这些数据举例说明了我拥有什么、我想要什么以及我尝试过什么。

#Example data that I have
Y.have<-cbind(c(19,1,1,1,1,4,3,1,1,8),c(3,1,1,1,1,2,1,1,1,3))

数据显示,第一行有 3 个项目的尺寸为 19,第二列有一个项目的尺寸为 1,以此类推。重要的是,在这些数据中最初有 15 个项目(即sum(Y.have[,2])),其中一些已合并,因此最终数据的长度需要为 15。

我希望数据看起来像:

####Homogenous separation - split values evenly as possible
#' The value of 19 in row 1 is now a vector of c(6,6,7) (or any combination thereof, i.e. c(6,7,6) is fine) since the position in the second column is a 3
#' Rows 2-5 are unchanged since they have a 1 in the second column
#' The value of 4 in row 6 is now a vecttor of c(2,2) since the position of the second column is a 2
#' Rows 7-9 are unchanged since they have a 1 in the second column
#' The value of 8 in row 10 is now a vector of c(3,3,2) (or any combination thereof) since the position in the second column is a 3
Y.want.hom<-cbind(c(c(6,6,7),1,1,1,1,c(2,2),3,1,1,c(3,3,2)),c(rep(1,times=sum(Y.have[,2]))))

####Heterogenous separation - split values with as many singles as possible, 
#' The value of 19 in row 1 is now a vector of c(1,1,17) (or any combination thereof, i.e. c(1,17,1) is fine) since the position in the second column is a 3
#' Rows 2-5 are unchanged since they have a 1 in the second column
#' The value of 4 in row 6 is now a vecttor of c(1,3) since the position of the second column is a 2
#' Rows 7-9 are unchanged since they have a 1 in the second column
#' The value of 8 in row 10 is now a vector of c(1,1,6) (or any combination thereof) since the position in the second column is a 3
Y.want.het<-cbind(c(c(1,1,17),1,1,1,1,c(1,3),3,1,1,c(1,1,6)),c(rep(1,times=sum(Y.have[,2]))))

请注意,整数在最终数据中的位置无关紧要,因为它们都有一个索引案例。

我已尝试根据索引大小写拆分数据 (split)。这将根据唯一索引值的数量创建具有长度的列表。然后我遍历该列表中的位置并除以位置。

a<-split(Y.have[,1],Y.have[,2]) #Split into a list according to the index
b<-list() #initiate new list
for (i in 1:length(a)){ 
  b[[i]]<-a[[i]]/i #get homogenous values
  b[[i]]<-rep(b[i],times=i) #repeat the values based on the number of indicies
}
Y.test<-cbind(unlist(b),rep(1,times=length(unlist(c)))) #create new dataset

这是一种糟糕的方法。首先,它将产生小数。其次,列表中的位置不一定等于索引号(即,如果没有索引 2,则第二个位置将是下一个最低索引,但会除以 2)。

但是,它至少允许我按索引分离数据,对其进行操作,并将其重新组合成适当的长度。我现在需要中间部分的帮助 - 处理同质和异质重新分配的数据。我更喜欢base r,但任何方法都可以!提前谢谢!

【问题讨论】:

    标签: r list split


    【解决方案1】:

    这可能是一种方法。

    为同构和异构拆分创建两个函数:

    get_hom_ints <- function(M, N) {
      vec <- rep(floor(M/N), N)
      for (i in seq_len(M - sum(vec))) {
        vec[i] <- vec[i] + 1
      }
      vec
    }
    
    get_het_ints <- function(M, N) {
      vec <- rep(1, N)
      vec[1] <- M - sum(vec) + 1
      vec
    }
    

    然后使用apply遍历矩阵的每一行:

    het_vec <- unlist(apply(Y.have, 1, function(x) get_het_ints(x[1], x[2]))) 
    unname(cbind(het_vec, rep(1, length(het_vec))))
    
    hom_vec <- unlist(apply(Y.have, 1, function(x) get_hom_ints(x[1], x[2])))
    unname(cbind(hom_vec, rep(1, length(het_vec))))
    

    输出

    (异构)

          [,1] [,2]
     [1,]   17    1
     [2,]    1    1
     [3,]    1    1
     [4,]    1    1
     [5,]    1    1
     [6,]    1    1
     [7,]    1    1
     [8,]    3    1
     [9,]    1    1
    [10,]    3    1
    [11,]    1    1
    [12,]    1    1
    [13,]    6    1
    [14,]    1    1
    [15,]    1    1
    

    (同质)

          [,1] [,2]
     [1,]    7    1
     [2,]    6    1
     [3,]    6    1
     [4,]    1    1
     [5,]    1    1
     [6,]    1    1
     [7,]    1    1
     [8,]    2    1
     [9,]    2    1
    [10,]    3    1
    [11,]    1    1
    [12,]    1    1
    [13,]    3    1
    [14,]    3    1
    [15,]    2    1
    

    【讨论】:

    • 这是一个完美而优雅的解决方案。在这两种情况下,您似乎首先分配了最简单的向量值,然后返回并添加了更复杂的东西(即在 'ho'm 中添加额外的 1 并在 'het' 中添加余数。谢谢你们提供帮助这里还有未来如何处理解决方案!
    【解决方案2】:

    library(partitions) 是为此类需求创建的,请查看。
    将以下逻辑应用于您的代码,它应该可以工作

    例如:

    hom <- restrictedparts(19,3)  #where 19 is Y.have[,1][1] and 3 is Y.have[,2][1] as per your data 
    print(hom[,ncol(hom)])
    
    #output : 7 6 6
    
    het <- Reduce(intersect, list(which(hom[2,1:ncol(hom)] %in% 1),which(hom[3,1:ncol(hom)] %in% 1)))
    hom[,het]
    
    #output : 17 1 1
    

    【讨论】:

      【解决方案3】:

      一种选择是使用整数除法 (%/%) 和模数 (%%)。它可能无法给出您指定的确切结果,即。 8 和 3 给出 (2,2,4) 而不是 (3,3,2),但通常会按照您的描述进行。

      Y.have<-cbind(c(19,1,1,1,1,4,3,1,1,8),c(3,1,1,1,1,2,1,1,1,3))
      
      homoVec <- c()
      for (i in 1:length(Y.have[,1])){
        if (Y.have[i,2] == 1) {
          a = Y.have[i,1]
          homoVec <- append(homoVec, a)
        } else {
          quantNum <- Y.have[i,1]
          indexNum <- Y.have[i,2]
          b <- quantNum %/% indexNum
          c <- quantNum %% indexNum
          a <- c(rep(b, indexNum-1), b + c)
          homoVec <- append(homoVec, a)
        }
      }
      
      homoOut <- data.frame(homoVec, 1)
      
      heteroVec <- c()
      for (i in 1:length(Y.have[,1])){
        if (Y.have[i,2] == 1) {
          a = 1
          heteroVec <- append(heteroVec, a)
        } else {
          quantNum <- Y.have[i,1]
          indexNum <- Y.have[i,2]
          firstNum <- quantNum - (indexNum - 1)
          a <- c(firstNum, rep(1, indexNum - 1))
          heteroVec <- append(heteroVec, a)
        }
      }
      
      heteroOut <- data.frame(heteroVec, 1)
      

      如果完全按照您在示例中描述的方式进行数学运算真的很重要,那么这应该可行。

      homoVec <- c()
      for (i in 1:length(Y.have[,1])){
        if (Y.have[i,2] == 1) {
          a = Y.have[i,1]
          homoVec <- append(homoVec, a)
        } else {
          quantNum <- Y.have[i,1]
          indexNum <- Y.have[i,2]
          b <- round(quantNum/indexNum)
          roundSum <- b * (indexNum - 1)
          c <- quantNum - roundSum
          a <- c(rep(b, indexNum-1), c)
          homoVec <- append(homoVec, a)
        }
      }
      
      homoOut <- data.frame(homoVec, 1)
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2020-01-12
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-08-02
        • 1970-01-01
        • 2021-01-27
        • 1970-01-01
        相关资源
        最近更新 更多