Создание новых столбцов на основе выбранных столбцов с вычислением соотношения по группам - PullRequest
0 голосов
/ 25 мая 2020

Мои данные выглядят следующим образом:

DF <- structure(list(No_Adjusted_Gross_Income = structure(c(1L, 1L, 
    2L, 2L, 3L, 3L), .Label = c("A", "B", "C"), class = "factor"), 
    NoR_from_1_to_5000 = c(1035373, 4272260, 1124098, 1035373, 
    4272260, 1124098), NoR_from_5000_to_10000 = c(319540, 4826042, 
    1959866, 319540, 4826042, 1959866), AGI_from_1_to_5000 = c(2588950186.5, 
    10682786130, 2810807049, 2588950186.5, 10682786130, 2810807049
    ), AGI_from_5000_to_10000 = c(2396550000, 36195315000, 14698995000, 
    2396550000, 36195315000, 14698995000)), class = "data.frame", row.names = c(NA, 
    -6L))

vn <- c("sum1", "sum2", "sum3", "sum4")

  No_Adjusted_Gross_Income NoR_from_1_to_5000 NoR_from_5000_to_10000 AGI_from_1_to_5000 AGI_from_5000_to_10000
1                        A            1035373                 319540         2588950187             2396550000
2                        A            4272260                4826042        10682786130            36195315000
3                        B            1124098                1959866         2810807049            14698995000
4                        B            1035373                 319540         2588950187             2396550000
5                        C            4272260                4826042        10682786130            36195315000
6                        C            1124098                1959866         2810807049            14698995000

Для каждого из столбцов со 2 по 5, я хотел бы создать новый столбец, который имеет в качестве своего значения исходное значение, разделенное на сумму значений на No_Adjusted_Gross_Income.

Я сначала попробовал с суммой:

DF[, (vn) := as.data.table ( t( t( DF[, 2:5, by=c("No_Adjusted_Gross_Income")] )) ) ][]

Но я получаю сообщение об ошибке:

Error in `:=`((vn), as.data.table(t(t(DF[, 2:5, by = c("No_Adjusted_Gross_Income")])))) : 
  Check that is.data.table(DT) == TRUE. Otherwise, := and `:=`(...) are defined for use in j, once only and in particular ways. See help(":=").

Как мне сделать это правильно? И могу ли я напрямую разделить значение исходного столбца на эту сумму?

Желаемый результат для сумм:

DF <- setDT(DF)[, sum_1 := sum(NoR_from_1_to_5000),by=c("No_Adjusted_Gross_Income")]
DF <- setDT(DF)[, sum_2 := sum(NoR_from_5000_to_10000),by=c("No_Adjusted_Gross_Income")]
DF <- setDT(DF)[, sum_3 := sum(AGI_from_1_to_5000),by=c("No_Adjusted_Gross_Income")]
DF <- setDT(DF)[, sum_4 := sum(AGI_from_5000_to_10000),by=c("No_Adjusted_Gross_Income")]
DF <- setDT(DF)[, rat_1 := NoR_from_1_to_5000/sum_1 ,by=c("No_Adjusted_Gross_Income")]
DF <- setDT(DF)[, rat_2 := NoR_from_5000_to_10000/sum_2 ,by=c("No_Adjusted_Gross_Income")]
DF <- setDT(DF)[, rat_3 := AGI_from_1_to_5000/sum_3,by=c("No_Adjusted_Gross_Income")]
DF <- setDT(DF)[, rat_4 := AGI_from_5000_to_10000/sum_4,by=c("No_Adjusted_Gross_Income")]

   No_Adjusted_Gross_Income NoR_from_1_to_5000 NoR_from_5000_to_10000 AGI_from_1_to_5000 AGI_from_5000_to_10000   sum_1   sum_2       sum_3       sum_4 rat_1 rat_2 rat_3
1:                        A            1035373                 319540         2588950187             2396550000 5307633 5145582 13271736317 38591865000  0.20 0.062  0.20
2:                        A            4272260                4826042        10682786130            36195315000 5307633 5145582 13271736317 38591865000  0.80 0.938  0.80
3:                        B            1124098                1959866         2810807049            14698995000 2159471 2279406  5399757236 17095545000  0.52 0.860  0.52
4:                        B            1035373                 319540         2588950187             2396550000 2159471 2279406  5399757236 17095545000  0.48 0.140  0.48
5:                        C            4272260                4826042        10682786130            36195315000 5396358 6785908 13493593179 50894310000  0.79 0.711  0.79
6:                        C            1124098                1959866         2810807049            14698995000 5396358 6785908 13493593179 50894310000  0.21 0.289  0.21
   rat_4
1: 0.062
2: 0.938
3: 0.860
4: 0.140
5: 0.711
6: 0.289

Ответы [ 3 ]

1 голос
/ 25 мая 2020

вот мой go у вещей ...

library( data.table )
#colnames for the ratio
rn <- c("rat_1", "rat_2", "rat_3", "rat_4")
#make DF a data.table
setDT( DF )
#calculate the sum-columns by No_Adjusted_Gross_Income
DF[, (vn) := lapply( .SD, sum, na.rm = TRUE ), by = .(No_Adjusted_Gross_Income), .SDcols = patterns( "^NoR|^AGI") ]
#calculate the ratio by simple dividion of two data.tables
DF[, (rn) := DF[, .SD, .SDcols = patterns("^NoR|^AGI")] / DF[, .SD, .SDcols = patterns("^sum")] ]

#    No_Adjusted_Gross_Income NoR_from_1_to_5000 NoR_from_5000_to_10000 AGI_from_1_to_5000 AGI_from_5000_to_10000
# 1:                        A            1035373                 319540         2588950187             2396550000
# 2:                        A            4272260                4826042        10682786130            36195315000
# 3:                        B            1124098                1959866         2810807049            14698995000
# 4:                        B            1035373                 319540         2588950187             2396550000
# 5:                        C            4272260                4826042        10682786130            36195315000
# 6:                        C            1124098                1959866         2810807049            14698995000
#       sum1    sum2        sum3        sum4     rat_1      rat_2     rat_3      rat_4
# 1: 5307633 5145582 13271736317 38591865000 0.1950725 0.06209988 0.1950725 0.06209988
# 2: 5307633 5145582 13271736317 38591865000 0.8049275 0.93790012 0.8049275 0.93790012
# 3: 2159471 2279406  5399757236 17095545000 0.5205432 0.85981436 0.5205432 0.85981436
# 4: 2159471 2279406  5399757236 17095545000 0.4794568 0.14018564 0.4794568 0.14018564
# 5: 5396358 6785908 13493593179 50894310000 0.7916932 0.71118589 0.7916932 0.71118589
# 6: 5396358 6785908 13493593179 50894310000 0.2083068 0.28881411 0.2083068 0.28881411
1 голос
/ 25 мая 2020

Как объяснено в мой другой ответ на вопрос, связанный с OP Используя lapply для создания новых столбцов на основе старых столбцов , я предлагаю хранить и обрабатывать данные в аккуратном формате , где есть одна строка для каждого наблюдения и один столбец для каждой переменной.

Преобразование предоставленного набора данных в длинный формат

library(data.table)
cols <- c("NoR", "AGI")
long <- melt(setDT(DF), measure.vars = patterns(cols), variable.name = "range", value.name = cols)
library(magrittr) # piping used to improve readability
rn <- names(DF) %>% stringr::str_subset("from") %>% stringr::str_remove("^.*(?=from)") %>% unique
long[, range := factor(range, labels = rn)]
long
    No_Adjusted_Gross_Income              range     NoR         AGI
 1:                        A     from_1_to_5000 1035373  2588950187
 2:                        A     from_1_to_5000 4272260 10682786130
 3:                        B     from_1_to_5000 1124098  2810807049
 4:                        B     from_1_to_5000 1035373  2588950187
 5:                        C     from_1_to_5000 4272260 10682786130
 6:                        C     from_1_to_5000 1124098  2810807049
 7:                        A from_5000_to_10000  319540  2396550000
 8:                        A from_5000_to_10000 4826042 36195315000
 9:                        B from_5000_to_10000 1959866 14698995000
10:                        B from_5000_to_10000  319540  2396550000
11:                        C from_5000_to_10000 4826042 36195315000
12:                        C from_5000_to_10000 1959866 14698995000

Поставляемый набор данных содержит несколько наборов столбцов мер, форма которых изменяется одновременно. Было бы легче начать с более простого набора данных, представленного в предыдущем вопросе OP .

Добавление крысы ios на группу

rat_cols <- paste0("rat_", cols)
long[,  (rat_cols) := lapply(.SD, function(x) x / sum(x)), .SDcols = cols, by = .(No_Adjusted_Gross_Income, range)]
long
    No_Adjusted_Gross_Income              range     NoR         AGI    rat_NoR    rat_AGI
 1:                        A     from_1_to_5000 1035373  2588950187 0.19507246 0.19507246
 2:                        A     from_1_to_5000 4272260 10682786130 0.80492754 0.80492754
 3:                        B     from_1_to_5000 1124098  2810807049 0.52054323 0.52054323
 4:                        B     from_1_to_5000 1035373  2588950187 0.47945677 0.47945677
 5:                        C     from_1_to_5000 4272260 10682786130 0.79169321 0.79169321
 6:                        C     from_1_to_5000 1124098  2810807049 0.20830679 0.20830679
 7:                        A from_5000_to_10000  319540  2396550000 0.06209988 0.06209988
 8:                        A from_5000_to_10000 4826042 36195315000 0.93790012 0.93790012
 9:                        B from_5000_to_10000 1959866 14698995000 0.85981436 0.85981436
10:                        B from_5000_to_10000  319540  2396550000 0.14018564 0.14018564
11:                        C from_5000_to_10000 4826042 36195315000 0.71118589 0.71118589
12:                        C from_5000_to_10000 1959866 14698995000 0.28881411 0.28881411

Преобразование в широкий формат

ИМХО, это требуется только для представления / печати данных в широком формате («стиль Excel»). Для последующей обработки, в частности построения графиков, я рекомендую сохранять данные в длинном формате («SQL стиль»).

dcast(long, No_Adjusted_Gross_Income + rowid(No_Adjusted_Gross_Income, range) ~ range, 
      value.var = c(cols, rat_cols))
   No_Adjusted_Gross_Income No_Adjusted_Gross_Income_1 NoR_from_1_to_5000 NoR_from_5000_to_10000
1:                        A                          1            1035373                 319540
2:                        A                          2            4272260                4826042
3:                        B                          1            1124098                1959866
4:                        B                          2            1035373                 319540
5:                        C                          1            4272260                4826042
6:                        C                          2            1124098                1959866
   AGI_from_1_to_5000 AGI_from_5000_to_10000 rat_NoR_from_1_to_5000 rat_NoR_from_5000_to_10000
1:         2588950187             2396550000              0.1950725                 0.06209988
2:        10682786130            36195315000              0.8049275                 0.93790012
3:         2810807049            14698995000              0.5205432                 0.85981436
4:         2588950187             2396550000              0.4794568                 0.14018564
5:        10682786130            36195315000              0.7916932                 0.71118589
6:         2810807049            14698995000              0.2083068                 0.28881411
   rat_AGI_from_1_to_5000 rat_AGI_from_5000_to_10000
1:              0.1950725                 0.06209988
2:              0.8049275                 0.93790012
3:              0.5205432                 0.85981436
4:              0.4794568                 0.14018564
5:              0.7916932                 0.71118589
6:              0.2083068                 0.28881411
1 голос
/ 25 мая 2020

Ваш код действительно работает для вычисления суммы, если вы конвертируете свой data.frame в data.table с setDT(DF)[,....] Если вам просто нужно соотношение, это, возможно, то, что вы после

setDT(DF)[,paste0("rat_",1:4) :=lapply(.SD, function (x) round(x/sum(x),3)),
.SDcols = 2:5,
by =.(No_Adjusted_Gross_Income)][]
...