Настройте набор значений в группе так, чтобы они суммировались точно до 100 - PullRequest
0 голосов
/ 20 июня 2019

Проверка данных на программной платформе настаивает на том, что ассигнования каждого человека должны быть целыми числами, которые в сумме равны 100. Скажем, человек распределяется 33-33-33 по трем проектам, один из которых должен быть скорректирован до 34 до подачипринятоЕсли 25-76, то одно из них должно быть уменьшено на 1. Неважно, что настраивается.

Вот примерные данные:

dat <- data.frame(person = c(1, 1, 1, 2, 2, 2),
                  proj = c("a", "b", "c", "a", "d", "e"),
                  alloc = c(40, 50, 11, 33, 33, 33))

dat
  person proj alloc
1      1    a    40
2      1    b    50
3      1    c    11
4      2    a    33
5      2    d    33
6      2    e    33

Правильно настроенные значения dat$alloc вэтот пример будет включать 39, 50, 11, 34, 33, 33 или 40, 50, 10, 33, 33, 34 и т. д.

Какой простой и простой способ сделать это?Прямо сейчас я создаю новый data.frame для вычисления корректировок, затем присоединяю его обратно, используя фиктивную переменную ID строки и т. Д. Я бы предпочел сделать это только в рамках операции dplyr group_by и избежать создания отдельных данных..frame.

Ответы [ 2 ]

1 голос
/ 20 июня 2019

Небольшое отклонение, при котором округлению присваивается наибольшее число:

library(dplyr)
dat2 <- dat %>%
  group_by(person) %>%
  arrange(person, -alloc, proj)) %>%
  mutate(alloc = alloc + if_else(row_number() == 1, 100 - sum(alloc), 0))
1 голос
/ 20 июня 2019

Вы можете просто заменить одно из значений на разницу между 100 и суммой других значений, например

dat %>% 
  group_by(person) %>% 
  mutate(alloc=c(100-sum(alloc[-1]), alloc[-1]))

Здесь мы заменяем первое значение alloc[1] на 100-sum(alloc[-1]) и сохраняем все остальные значения.

...