给定桶大小按体积填充容器
Filling containers by volume given a bucket size
假设我有一个包含序列号容器及其各自体积的数据集。
x <- data.frame("SN" = 1:3, "Price" = c(10,20,30), "Volume" = c(100,150,200))
SN Price Volume
1 10 100
2 20 150
3 30 200
我想用给定尺寸的桶装满容器。
- 如果容器在桶被清空之前被填满,我想
移动到下一个 SN。
- 如果桶先于容器清空
装满了,我想用剩下的容器开始新的一行。
bucket_size = 200 时的期望输出:
SN Price Volume
1 10 100 # max for SN 1 is 100, totally filled, bucket now = 100
2 20 100 # max for SN 2 is 150, bucket now = 0
2 20 50 # fill remaining SN 2, new bucket now = 150
3 30 150 # max for SN 3 is 200, bucket now = 0
3 30 50 # fill remaining in SN 3, bucket now = 150 remaining
我已经开始编码,但我的代码似乎不够通用,无法适用于任何存储桶大小。
x <- data.frame("SN" = 1:3, "Price" = c(10,20,30), "Volume" = c(100,150,200))
bucketsize <- 200
PendingBucketVolume <- bucketsize
y <- data.frame(SN = integer(),Price=numeric(),Volume=numeric(),stringsAsFactors=FALSE)
for (i in 1:nrow(x)) {
if (x$Volume[i] <= PendingBucketVolume) {
print(x$Volume[i])
PendingBucketVolume <- PendingBucketVolume - x$Volume[i]
} else {
print(PendingBucketVolume)
remainder <- x$Volume[i] - PendingBucketVolume
if (remainder <= bucketsize) {
print(remainder)
} else {
print(bucketsize)
remainder <- remainder - bucketsize
}
if (remainder < PendingBucketVolume) {
PendingBucketVolume <- remainder
} else {
PendingBucketVolume <- bucketsize
PendingBucketVolume <- PendingBucketVolume - remainder
}
}
}
关于使其通用且高效的建议。
我花了太长时间试图让 if else
逻辑为此工作。行卷和桶卷的平衡过多。相反,我想我可以把所有的卷都拆开并给它们分配一个 ID,cbind
它们,然后使用 table 将它们重新组合在一起。结果可能是比 if else
方法慢得多的计算,但代码非常简单。
x <- data.frame("SN" = 1:3, "Price" = c(10,20,30), "Volume" = c(100,150,200))
allocate_buckets <- function(x, bucketsize){
# assumption that X has the colnames
stopifnot(colnames(x) == c("SN","Price","Volume"))
row_num <- rep(x[,"SN"], x[,"Volume"])
l <- length(row_num)
bucket_num <- rep(1:ceiling(l/bucketsize), each = bucketsize)[1:l]
out <- table(row_num, bucket_num)
out.ind <- which(out !=0, arr.ind = T)
return(cbind.data.frame(x[out.ind[,1],c("SN","Price")], Volume = out[out.ind]))
}
现在您可以将它用于任何(整数)卷:
allocate_buckets(x, 200)
# SN Price Volume
#1 1 10 100
#2 2 20 100
#2.1 2 20 50
#3 3 30 150
#3.1 3 30 50
allocate_buckets(x, 67)
# SN Price Volume
#1 1 10 67
#1.1 1 10 33
#2 2 20 34
#2.1 2 20 67
#2.2 2 20 49
#3 3 30 18
#3.1 3 30 67
#3.2 3 30 67
#3.3 3 30 48
编辑
太棒了 link 你发帖了,我离这个太近了,这是 R 版本:
x <- data.frame("SN" = 1:3, "Price" = c(10,20,30), "Volume" = c(100,150,200))
y <- data.frame(SN = integer(), Price = numeric(), Volume = numeric())
bucket <- bucketsize <- 200
vol <- numeric()
count <- 0
for(i in 1:nrow(x)){
volume <- x[i,"Volume"]
while(volume!=0){
vol <- min(volume, bucket)
print(vol)
count <- count + 1
y[count,] <- x[i,]
y[count,"Volume"] <- vol
volume <- volume - vol
bucket <- bucket - vol
if(bucket == 0){
bucket <- bucketsize
}
}
}
编辑 2
我 运行 对这两种方法进行了微基准测试(花了一段时间),结果是与 SAS 编写的代码 t运行 相比,我原来的方法实际上看起来更快。
expr min lq mean median uq max neval
allocate_buckets(x, 200) 312.4177 466.6347 504.2121 483.1754 516.2977 846.4529 100
other(x, 200) 986.6495 1233.5141 1339.4219 1265.3606 1389.1158 2023.7884 100
这出乎我的意料。另一种方法的好处是它可以处理非整数值。人们可能可以通过使用 data.tables 来加速 allocate_buckets 函数,并且可以通过乘以 100 或任何使最小小数成为整数的数字,然后将结果除以来解除非整数约束100之后。
假设我有一个包含序列号容器及其各自体积的数据集。
x <- data.frame("SN" = 1:3, "Price" = c(10,20,30), "Volume" = c(100,150,200))
SN Price Volume
1 10 100
2 20 150
3 30 200
我想用给定尺寸的桶装满容器。
- 如果容器在桶被清空之前被填满,我想 移动到下一个 SN。
- 如果桶先于容器清空 装满了,我想用剩下的容器开始新的一行。
bucket_size = 200 时的期望输出:
SN Price Volume
1 10 100 # max for SN 1 is 100, totally filled, bucket now = 100
2 20 100 # max for SN 2 is 150, bucket now = 0
2 20 50 # fill remaining SN 2, new bucket now = 150
3 30 150 # max for SN 3 is 200, bucket now = 0
3 30 50 # fill remaining in SN 3, bucket now = 150 remaining
我已经开始编码,但我的代码似乎不够通用,无法适用于任何存储桶大小。
x <- data.frame("SN" = 1:3, "Price" = c(10,20,30), "Volume" = c(100,150,200))
bucketsize <- 200
PendingBucketVolume <- bucketsize
y <- data.frame(SN = integer(),Price=numeric(),Volume=numeric(),stringsAsFactors=FALSE)
for (i in 1:nrow(x)) {
if (x$Volume[i] <= PendingBucketVolume) {
print(x$Volume[i])
PendingBucketVolume <- PendingBucketVolume - x$Volume[i]
} else {
print(PendingBucketVolume)
remainder <- x$Volume[i] - PendingBucketVolume
if (remainder <= bucketsize) {
print(remainder)
} else {
print(bucketsize)
remainder <- remainder - bucketsize
}
if (remainder < PendingBucketVolume) {
PendingBucketVolume <- remainder
} else {
PendingBucketVolume <- bucketsize
PendingBucketVolume <- PendingBucketVolume - remainder
}
}
}
关于使其通用且高效的建议。
我花了太长时间试图让 if else
逻辑为此工作。行卷和桶卷的平衡过多。相反,我想我可以把所有的卷都拆开并给它们分配一个 ID,cbind
它们,然后使用 table 将它们重新组合在一起。结果可能是比 if else
方法慢得多的计算,但代码非常简单。
x <- data.frame("SN" = 1:3, "Price" = c(10,20,30), "Volume" = c(100,150,200))
allocate_buckets <- function(x, bucketsize){
# assumption that X has the colnames
stopifnot(colnames(x) == c("SN","Price","Volume"))
row_num <- rep(x[,"SN"], x[,"Volume"])
l <- length(row_num)
bucket_num <- rep(1:ceiling(l/bucketsize), each = bucketsize)[1:l]
out <- table(row_num, bucket_num)
out.ind <- which(out !=0, arr.ind = T)
return(cbind.data.frame(x[out.ind[,1],c("SN","Price")], Volume = out[out.ind]))
}
现在您可以将它用于任何(整数)卷:
allocate_buckets(x, 200)
# SN Price Volume
#1 1 10 100
#2 2 20 100
#2.1 2 20 50
#3 3 30 150
#3.1 3 30 50
allocate_buckets(x, 67)
# SN Price Volume
#1 1 10 67
#1.1 1 10 33
#2 2 20 34
#2.1 2 20 67
#2.2 2 20 49
#3 3 30 18
#3.1 3 30 67
#3.2 3 30 67
#3.3 3 30 48
编辑
太棒了 link 你发帖了,我离这个太近了,这是 R 版本:
x <- data.frame("SN" = 1:3, "Price" = c(10,20,30), "Volume" = c(100,150,200))
y <- data.frame(SN = integer(), Price = numeric(), Volume = numeric())
bucket <- bucketsize <- 200
vol <- numeric()
count <- 0
for(i in 1:nrow(x)){
volume <- x[i,"Volume"]
while(volume!=0){
vol <- min(volume, bucket)
print(vol)
count <- count + 1
y[count,] <- x[i,]
y[count,"Volume"] <- vol
volume <- volume - vol
bucket <- bucket - vol
if(bucket == 0){
bucket <- bucketsize
}
}
}
编辑 2 我 运行 对这两种方法进行了微基准测试(花了一段时间),结果是与 SAS 编写的代码 t运行 相比,我原来的方法实际上看起来更快。
expr min lq mean median uq max neval
allocate_buckets(x, 200) 312.4177 466.6347 504.2121 483.1754 516.2977 846.4529 100
other(x, 200) 986.6495 1233.5141 1339.4219 1265.3606 1389.1158 2023.7884 100
这出乎我的意料。另一种方法的好处是它可以处理非整数值。人们可能可以通过使用 data.tables 来加速 allocate_buckets 函数,并且可以通过乘以 100 或任何使最小小数成为整数的数字,然后将结果除以来解除非整数约束100之后。