我如何通过百分比向量来分配一个数字向量,对结果进行四舍五入,并始终得到与我在R中开始时相同的总数? 问题摘要

我如何通过百分比向量来分配一个数字向量,对结果进行四舍五入,并始终得到与我在R中开始时相同的总数? 问题摘要,r,dataframe,aggregate,rounding,percentage,R,Dataframe,Aggregate,Rounding,Percentage,我想将一个数字向量(按组求和列)乘以一个百分比向量(百分比列),将组的总数分配到每个ID中,对结果进行四舍五入,最后得到与我开始时相同的总数。换句话说,我希望Distribution\u Post\u Round列与Sum\u By\u Group列相同 下面是我遇到的问题的一个例子。在A组中,我将百分比乘以Sum_by_Group,最后在ID 1中取3,ID 2中取3,ID 5中取1,总共取7。对于A组,Sum\u By\u Group列和Distribution\u Post\u Round

我想将一个数字向量(按组求和列)乘以一个百分比向量(百分比列),将组的总数分配到每个ID中,对结果进行四舍五入,最后得到与我开始时相同的总数。换句话说,我希望
Distribution\u Post\u Round
列与
Sum\u By\u Group
列相同

下面是我遇到的问题的一个例子。在A组中,我将
百分比
乘以
Sum_by_Group
,最后在ID 1中取3,ID 2中取3,ID 5中取1,总共取7。对于A组,
Sum\u By\u Group
列和
Distribution\u Post\u Round
列是相同的,这就是我想要的。在B组中,我将
百分比
乘以
Sum\u by\u组
,最后在ID 8中加1,在ID 10中加1,总共加2。我希望B组的
Distribution\u Post\u Round
列为3

有没有一种方法可以做到这一点,而不用使用循环、对数据帧进行子集设置,然后将数据帧重新连接在一起

例子
非常感谢你的帮助。如果需要进一步澄清,请告诉我。

哇,谁知道有人已经编写了一个包含解决此问题的函数的包

既然您似乎愿意使用dplyr,那么希望这个附加包是值得的,因为它肯定会使解决方案变得优雅

#https://stackoverflow.com/questions/61667720
图书馆(dplyr)
df=data.frame('Group')=c(rep('A',7),rep('B',5)),
“ID”=c(1:12),
“百分比”=c(0.413797750、0.385366840、0.014417571、0.060095668、0.076399650、,
0.019672573, 0.030249949, 0.381214519, 0.084121796, 0.438327886,
0.010665749, 0.085670050),
“按组求和”=c(代表(7,7),代表(3,5)))
一瞥(df)
#>行数:12
#>栏目:4
#>$A组、A组、A组、A组、A组、A组、A组、B组、B组、B组、“…
#>$ID1,2,3,4,5,6,7,8,9,10,11,12
#>百分之0.41379775,0.38536684,0.01441757,0.06009567,0.076399…
#>$Sum_按组7、7、7、7、7、7、3、3、3、3
df%>%
分组依据(分组)%>%
变异(按组分配)
#>#tibble:12 x 5
#>#组:组[2]
#>组ID按组分配的百分比总和
#>                            
#>1A 10.414 7 3
#>2 A 20.385 7 3
#>3A 30.0144 7 0
#>4a40.060170
#>5 A 5 0.0764 7 1
#>6 A 6 0.0197 7 0
#>7 A 7 0.0302 7 0
#>8 B 80.381 3 1
#>9B90.084130
#>10 B 10 0.438 3 2
#>11 B 11 0.0107 3 0
#>12 B 12 0.0857 3 0
由(v0.3.0)于2020-05-07创建 变动(股息=下限(百分比*各集团的总和), 剩余=百分比*集团股息之和%>% 分组依据(分组)%>% 排列(desc(余数),.by_group=TRUE)%>% 变动(交付=总额(股息), rownumber=1:n(), lastdelivery=if_else(行数% 解组() #一个tibble:12x10 组ID百分比总和按组红利剩余已交付行数lastdelivery Final 1 A 10.414 7 2 0.897 4 1 3 2 A 20.385 7 2 0.698 4 2 1 3 3 A 50.0764 70.535 4 3 1 4 A 40.0601 70.421 4 0 0 5 A 7 0.0302 7 0.212 4 5 0 0 6A60.019770.138 460 7A30.014470.101470 8B10.438310.315212 9B120.085730.2572200 10B90.0841300.2522300 11 B 80.381 3 1 0.144 2 4 0 1 12 B 11 0.0107 3 0.0320 2 5 0 0 0 这是我的解决方案,没有依赖于配额的任何其他依赖项: 我分配了所有的整数“席位”,然后我按照余数的顺序分配剩余的“席位”。 “Final”列就可以了


注意:它似乎给出了与其他解决方案相同的结果,该解决方案包含一个包

将其表述为一个整数优化问题:

library(CVXR)
A <- as.data.frame.matrix(t(model.matrix(~0+Group, df)))
prop <- df$Percent * df$Sum_By_Group
x <- Variable(nrow(df), integer=TRUE)
sums <- df$Sum_By_Group[!duplicated(df$Group)]
p <- Problem(Minimize(sum_squares(x - prop)), list(A %*% x == sums))
result <- solve(p)

df$Distribute_By_ID <- as.integer(round(result$getValue(x)))

您好,我手头没有电脑,但如果轮数之和大于总和,我认为您有一个错误。举例来说,2的总和将分布在0,33的3个相等百分比之间。您可以选择地板,然后按照我的建议执行兔子配额,或者您可以在替换中执行+/-1。:)@阿诺德费尔德曼感谢你指出这一点。我已经尝试了一种优化方法。
library(CVXR)
A <- as.data.frame.matrix(t(model.matrix(~0+Group, df)))
prop <- df$Percent * df$Sum_By_Group
x <- Variable(nrow(df), integer=TRUE)
sums <- df$Sum_By_Group[!duplicated(df$Group)]
p <- Problem(Minimize(sum_squares(x - prop)), list(A %*% x == sums))
result <- solve(p)

df$Distribute_By_ID <- as.integer(round(result$getValue(x)))
   Group ID    Percent Sum_By_Group
1      A  1 0.41379775            7
2      A  2 0.38536684            7
3      A  3 0.01441757            7
4      A  4 0.06009567            7
5      A  5 0.07639965            7
6      A  6 0.01967257            7
7      A  7 0.03024995            7
8      B  8 0.38121452            3
9      B  9 0.08412180            3
10     B 10 0.43832789            3
11     B 11 0.01066575            3
12     B 12 0.08567005            3