我有两个数据框
DF1
包含分配给某个区域的唯一ID以及每个ID中有多少人的计数。 (COUNT
列)。
DF2
包含需要为区域分配多少人(CHANGE
列)。
是否有一种有效的方法,例如,在区域A的情况下,将CHANGE
中DF2
列的额外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)]}}
答案 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