在数据框中的多行中随机分布值

时间:2017-02-01 10:08:14

标签: r dataframe

我有两个数据框 DF1包含分配给某个区域的唯一ID以及每个ID中有多少人的计数。 (COUNT列)。
DF2包含需要为区域分配多少人(CHANGE列)。

是否有一种有效的方法,例如,在区域A的情况下,将CHANGEDF2列的额外24个人添加到COUNT中的DF1列}随机分配给区域A的行。
谢谢。

DF1 <- data.frame(matrix(0, nrow=20, ncol=3))
DF1[,1] <- 1:20
DF1[,2] <- rep(c("A","B","C","D"), each=5)
DF1[,3] <- sample(10:30,20,rep=TRUE)
colnames(DF1) <- c("ID","AREA","COUNT")

DF2 <- data.frame(matrix(0, nrow=4, ncol=2))
DF2[,1] <- c("A","B","C","D")
DF2[,2] <- c(24,-17,-1,5)
colnames(DF2) <- c("AREA","CHANGE")

编辑: 这是我目前的解决方案。但是,我的实际数据集包含数千行,需要几个小时才能完成。因此,为什么我会采用更有效的方式来实现同一目标。

for (i in 1:length(unique(DF2[,1]))){
DF_Area <- unique(DF1[,2])
DF1_Subset <- with(DF1, DF1[AREA == DF_Area[i],])
DF2_Row <- DF2[DF2$AREA %in% DF_Area[i],]

if(DF2_Row$CHANGE!=0){
DF1_Update <- as.data.frame(DF1_Subset$COUNT)

if(DF2_Row$CHANGE>=0){ALLOCATION_VALUE <- 1}else{ALLOCATION_VALUE <- -1}

for (GG in 1:abs(DF2_Row$CHANGE)){
DF1_Update_Row <- sample(which(DF1_Update > 0),1)
DF1_Update[DF1_Update_Row, ] <- DF1_Update[DF1_Update_Row, ] + ALLOCATION_VALUE}

DF1_Subset$COUNT <- DF1_Update[,1]
DF1$COUNT[match(DF1$ID, DF1_Subset$ID, nomatch = 0) != 0] <- DF1_Subset$COUNT[match(DF1$ID, DF1_Subset$ID, nomatch = 0)]}}

2 个答案:

答案 0 :(得分:1)

这适用于任意数量的区域和任何ID号,但如果ID中删除了太多人,则可以给出负数

library(data.table)

DF1 <- as.data.table(DF1,key="ID")
DF1$AREA <- as.factor(DF1$AREA)  #to change area as level
dt_all <-NULL

for (i in levels(DF1$AREA)) {

  if (DF2[DF2$AREA == i,]$CHANGE != 0) {
    bool_pos <- (DF2[DF2$AREA == i,]$CHANGE > 0) #to know to add or remove from count

    ID <- sample(1:(length(DF1[AREA == i,]$ID)),abs(DF2[DF2$AREA == i,]$CHANGE), rep=TRUE)
    ID <- DF1[AREA == i,]$ID[ID] # select random id for each value in change
    df_temp <- as.data.table(table(ID),key="ID") 
    df_temp$ID <- as.integer(df_temp$ID)
    if (!bool_pos) {
      df_temp$N <- (df_temp$N)*-1
    }

    dt_all <- rbind(dt_all,df_temp )
  }
}

DF1 <- merge(DF1, dt_all,all.x=TRUE, by="ID")  
DF1[is.na(N), N:=0]
DF1[, COUNT:=COUNT+N]
DF1[,N:=NULL]
dt_all <-NULL

答案 1 :(得分:1)

这也应该起作用(每次通过将总CHANGE分成等于产生每个剩余数字的相等间隔来生成随机数)。此外,使用C:\\Program Files\\Microsoft Office 15\\Root\\Office15\\MSWORD.OLB 而不是内部循环子集,它会更快。

split