我有170行带小数的数字需要舍入到整数.但是,行总数必须等于我指定的数字.
作为一个非常基本的例子,假设我有一个矩阵(1×4)与单元格内容(1.2,3.4,7.7,5.3).但是,让我们说这些数字代表个体,所以我需要将它们四舍五入到整数,这样群体人口就等于18个人的总人口.如果我简单地舍入矩阵内容,这给了我(1,3,8,5),我的总人口是17,我需要它等于18(参见下面的R命令).
m <- c(1.2, 3.4, 7.7, 5.3)
m.2 <- round(m)
m.2
[1] 1 3 8 5sum(m.2)
[1] 17
数字四舍五入后,我需要R然后选择最接近于向上舍入的下一个数字(即3.4)并将其四舍五入为4而不是3.
这将给我一个(1,4,8,5)= 18的矩阵.
约翰福克斯博士用一个简单的递归函数帮我解决了这个问题:
Round <- function(x, target){
r.x <- round(x)
diff.x <- round(x) - x
if ((s <- sum(r.x)) == target) return(r.x)
else if (s > target) {
select <- seq(along=x)[diff.x > 0]
which <- which.max(diff.x[select])
x[select[which]] <- r.x[select[which]] - 1
Round(x, target)
}
else{
select <- seq(along=x)[diff.x < 0]
which <- which.min(diff.x[select])
x[select[which]] <- r.x[select[which]] + 1
Round(x, target)
}
}
这对于各行非常有用.但我的数据集中有170行.这意味着重复这样的过程(见下文)170次:
paste(STATA[['b']], collapse=", ") B <- c(46.8310012817383, 19.9720001220703, 265.837005615234, 95.0400009155273, 6.88700008392334, 190.768997192383, 22.7269992828369, 764.453002929688, 53.0299987792969, 333.329010009766, 55.0960006713867, 84.0210037231445, 28.2369995117188, 2207.27099609375, 86.7760009765625, 50045.46875, 103.304000854492, 413.217987060547, 4.13199996948242, 2.75500011444092, 183.88200378418, 65.4260025024414, 0.689000010490417, 2248.59204101562, 0, 1.37699997425079, 16.5289993286133, 4.13199996948242, 4.13199996948242, 2.75500011444092, 4.13199996948242, 1.37699997425079, 0, 39.9440002441406, 2.75500011444092, 28.2369995117188, 0, 0, 5.51000022888184, 0, 48.8969993591309, 17.9
Round <- function(x, target){ r.x <- round(x) diff.x <- round(x) - x if ((s <- sum(r.x)) == target) return(r.x) else if (s > target) { select <- seq(along=x)[diff.x > 0] which <- which.max(diff.x[select]) x[select[which]] <- r.x[select[which]] - 1 Round(x, target) } else{ select <- seq(along=x)[diff.x < 0] which <- which.min(diff.x[select]) x[select[which]] <- r.x[select[which]] + 1 Round(x, target) } }
1373291, 485.531005859375, 1.37699997425079, 59.9169998168945, 221.759994506836, 28.2369995117188, 4.13199996948242, 65.4260025024414, 11.0190000534058, 38.5670013427734, 3.44300007820129, 8.95300006866455, 2.75500011444092, 23.4160003662109, 4.13199996948242, 50.5750015258789, 11.7
m <- c(1.2, 3.4, 7.7, 5.3)
m.2 <- round(m)
m.2
[1] 1 3 8 5sum(m.2)
[1] 171831055, 19.2830009460449, 48.8969993591309, 0, 13.7740001678467, 92.9739990234375)
varB <- (Round(B, 58701))
ROUND2012$varB <- varB
^在这种情况下,我在Excel中使用了数据集的转置,因为我发现与附加行相比,将列附加到R中的数据集更容易.但理想情况下,我不必这样做,行将是我的领地,列是组身份人口数据.这里,’b’是我正在调用的列的名称,而58701是数字在舍入后需要累加的总数.
简而言之,我正在寻找一个对整个数据集而不是单个行有用的函数.理想情况下,我可以使用要舍入的数字来调用列,也可以使用我需要舍入数字等于的总数来调用列.
更新的信息
作为更具说明性的例子.假设我的人口中有两个种族群体.
B
race1 race2 total place1 1.2 2.1 3.4 place2 3.4 3.6 7.0 place3 7.7 0.8 8.5 place4 5.3 1.4 6.7
我需要这些数字等于我的登记选民总数.总计是3.4,7.0,8.5,6.7,但我需要对每个地方行内的内容进行舍入,以使我的位置(1-4)总计为4.0,7.0,8.0和7.0.因此对于place1来说,我需要对内容进行舍入,以便1.2变为2.0,2.1变为2.0.等于4.0,我的登记选民人数.对于place2,总数已经是7,所以我们没事.对于place3 7.7将变为7.0,0.8将变为1,总共给出8.最后对于place4,我需要5.3舍入到5和1.4舍入到2.0,总共给我7.我想要的是:
B
race1 race2 total place1 2.0 2.0 4.0 place2 3.0 4.0 7.0 place3 7.0 1.0 8.0 place4 5.0 2.0 7.0
目前上面粘贴的圆形功能允许我一次调用一系列数字,并手动输入需要舍入的总数.但我正在寻找能够同时完成所有这一切的功能.我想将所有竞赛列调整为四舍五入,并调用包含所有必要总人口的列.
(注意:实际上我已经在excel中对矩阵进行了转置并将其重新导入到R中,因为作为一个相当新的R用户,我发现将新列附加到数据集比添加新行更容易.但是我绝对不需要做那一步,事实上,我宁愿不这样做.)最佳答案 有几种方法可以做到这一点,但从上面我的评论:
Round <- function(x, target) { r.x <- round(x) diff.x <- round(x) - x if ((s <- sum(r.x)) == target) { return(r.x) } else if (s > target) { select <- seq(along=x)[diff.x > 0] which <- which.max(diff.x[select]) x[select[which]] <- r.x[select[which]] - 1 Round(x, target) } else { select <- seq(along=x)[diff.x < 0] which <- which.min(diff.x[select]) x[select[which]] <- r.x[select[which]] + 1 Round(x, target) } } dat <- read.table(header = TRUE, row.names = paste0('place', 1:4), text="race1 race2 total 1.2 2.1 3.4 3.4 3.6 7.0 7.7 0.8 8.5 5.3 1.4 6.7") totals <- c(4.0, 7.0, 8.0, 7.0)
这两个示例使用来自两列dat的1-1映射简单地在每行上执行Round,其中每个对应的值在总计中
lapply返回一个列表,因此要将输出转换回矩阵/数据框,我们将所有内容重新组合在一起.
do.call(rbind, lapply(1:nrow(dat), function(x) Round(dat[x, -3], totals[x]))) # race1 race2 # place1 2 2 # place2 3 4 # place3 7 1 # place4 5 2
apply的输出转换为你想要的,所以我们得到了结果
dat[3] <- totals t(apply(dat, 1, function(x) Round(x[1:2], x[3]))) # race1 race2 # place1 2 2 # place2 3 4 # place3 7 1 # place4 5 2
或者,您可以使用Map / mapply或Vectorize the Round来提供更聪明的东西以避免这些循环,但看起来您的数据看起来并不是很大.