I want to write a script to help me distribute piglets over pens while maintaining a similar average weight between pens by switching animals (rows) between pens to achieve this, but only switching piglets which have the same mother (i.e. the same sowid). So far I got the following script which leads to some improvement but I suspect it is not the optimal algorithm to achieve this goal. Any better ideas?
test <- data.table(sowid=c(12,23,25,45,65,12,58,85,96,85,45,23),pen=c(1,1,1,1,2,2,2,2,3,3,3,3),pigletid=c(1,2,3,4,5,6,7,8,9,10,11,12),weight=c(6.5,5.9,6.2,5.8,7.5,7.2,7.8,6.9,9.5,10.2,9.8,6.4))
count <- 0
switch <- c(0,0)
cutoff <- 0.1
while(count == 0){
meanPP <- test [,mean(weight),.(pen)]
names(meanPP) <- c("pen","Mean")
meanPP <- meanPP[order(Mean)]
if (max(meanPP$Mean) - min(meanPP$Mean) <= cutoff){
test <- test[order(pen)]
count <- count + 1
}else{
count2 <- 0
i <- 0
while (count2 == 0 & i <= nrow(meanPP)){
maxH <- meanPP$pen[nrow(meanPP)-i]
for (j in (nrow(test)/nrow(meanPP)):1){
maxA <- test[pen==maxH]
maxA <- maxA[order(weight)]$pigletid[j]
if ((test$sowid[which(test$pigletid == maxA)] %in% test$sowid[-which(test$pigletid == maxA)]) && test[sowid == test$sowid[which(test$pigletid == maxA)],min(weight)] < test[pigletid == maxA,weight]){
maxA <- which(test$pigletid == maxA)
count2 <- count2 +1
break
}
}
i <- i + 1
}
for (i in 1:nrow(meanPP)) {
minH <- meanPP$pen[i]
minA <- test[pen==minH]
if (test$sowid[maxA] %in% minA$sowid && minA[sowid==test$sowid[maxA]]$weight < test$weight[maxA]){
minA <- minA[sowid==test$sowid[maxA]]
minA <- minA[sowid==test$sowid[maxA]]$pigletid
minA <- which(test$pigletid == minA)
break
}
}
if (minA == switch[2] & maxA == switch[1]){
count <- count +1
}
switch <- c(minA,maxA)
tempRow <- test$pen[maxA]
test$pen[maxA] <- test$pen[minA]
test$pen[minA] <- tempRow
test <- test[order(pen)]
}
}
In response to Anurag N. Sharma, I would like output something like this:
> test
sowid pen pigletid weight
1: 25 1 3 6.2
2: 45 1 11 9.8
3: 23 1 12 6.4
4: 12 1 6 7.2
5: 12 2 1 6.5
6: 65 2 5 7.5
7: 58 2 7 7.8
8: 85 2 8 6.9
9: 85 3 10 10.2
10: 23 3 2 5.9
11: 45 3 4 5.8
12: 96 3 9 9.5
Where I can get the mean weight of each pen within as close to 0.1 difference as possible to the other pens.