Использование lapply для создания новых столбцов на основе старых столбцов - PullRequest
0 голосов
/ 25 мая 2020

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

DF <- structure(list(No_Adjusted_Gross_Income = c(183454, 241199, 249506
), NoR_from_1_to_5000 = c(1035373, 4272260, 1124098), NoR_from_5000_to_10000 = c(319540, 
4826042, 1959866)), row.names = c(NA, -3L), class = c("data.table", 
"data.frame"))
val <- c(2500.5, 7500)
vn <- c("AGI_from_1_to_5000", "AGI_from_5000_to_10000")

   No_Adjusted_Gross_Income NoR_from_1_to_5000 NoR_from_5000_to_10000
1:                   183454            1035373                 319540
2:                   241199            4272260                4826042
3:                   249506            1124098                1959866

Я хотел бы создать новые столбцы на основе столбцов 2 и 3, умноженные на значения из val, используя имена из vn. Я пытался сделать это так:

DF[,2:3] <- lapply(DF[,2:3], vn := val*DF[,2:3])

Но это не работает ..

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

DF <- setDT(DF)[, vn[1]:=val[1]*DF[,2]]
DF <- setDT(DF)[, vn[2]:=val[2]*DF[,3]]

DFout <- structure(list(No_Adjusted_Gross_Income = c(183454, 241199, 249506
), NoR_from_1_to_5000 = c(1035373, 4272260, 1124098), NoR_from_5000_to_10000 = c(319540, 
4826042, 1959866), AGI_from_1_to_5000 = c(2588950186.5, 10682786130, 
2810807049), AGI_from_5000_to_10000 = c(2396550000, 36195315000, 
14698995000)), row.names = c(NA, -3L), class = c("data.table", 
"data.frame"))

   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:                   183454            1035373                 319540         2588950187             2396550000
2:                   241199            4272260                4826042        10682786130            36195315000
3:                   249506            1124098                1959866         2810807049            14698995000

Ответы [ 3 ]

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

вы можете использовать apply, чтобы получить свои значения, затем используйте cbind, если вы хотите объединить с исходным DF

t(apply(DF[,2:3],1, function(x) x*val ))

 NoR_from_1_to_5000 NoR_from_5000_to_10000
[1,]         2588950187             2396550000
[2,]        10682786130            36195315000
[3,]         2810807049            14698995000
1 голос
/ 25 мая 2020

OP запросил комментарий для группирующей переменной.

Хотя принятый ответ, по-видимому, делает то, о чем первоначально просил OP, я хотел бы предложить совершенно другой подход, где данные хранятся и обрабатываются в формате tidy (long) . IMHO, обработка данных в длинном формате намного более проста и гибка (включая агрегацию и группировку).

Для этого набор данных изменяется с широкого формата в стиле Excel на длинный формат в стиле SQL by

library(data.table)
col <- "NoR"
long <- melt(DF, measure.vars = patterns(col), value.name = col, variable.name = "range")
long[, range := stringr::str_remove(range, paste0(col, "_"))]
long
   No_Adjusted_Gross_Income              range     NoR
1:                   183454     from_1_to_5000 1035373
2:                   241199     from_1_to_5000 4272260
3:                   249506     from_1_to_5000 1124098
4:                   183454 from_5000_to_10000  319540
5:                   241199 from_5000_to_10000 4826042
6:                   249506 from_5000_to_10000 1959866

В аккуратном (длинном) формате есть одна строка для каждого наблюдения и один столбец для каждой переменной (см. главу 12.2 книги Хэдли Уикхема R для науки о данных .

Вектор множителей val также необходимо изменить с широкого на длинный формат:

valDF <- long[, .(range = unique(range), val)]
valDF
                range    val
1:     from_1_to_5000 2500.5
2: from_5000_to_10000 7500.0

Теперь valDF также имеет аккуратный формат, так как для каждого range есть одна строка.

Наконец, мы можем добавить новый столбец AGI в DF с помощью обновление соединения :

long[valDF, on = "range", AGI := val * NoR][]
   No_Adjusted_Gross_Income              range     NoR         AGI
1:                   183454     from_1_to_5000 1035373  2588950187
2:                   241199     from_1_to_5000 4272260 10682786130
3:                   249506     from_1_to_5000 1124098  2810807049
4:                   183454 from_5000_to_10000  319540  2396550000
5:                   241199 from_5000_to_10000 4826042 36195315000
6:                   249506 from_5000_to_10000 1959866 14698995000

Если требуется для презентации, набор данных может быть преобразован из длинного в широкий формат:

dcast(long, No_Adjusted_Gross_Income ~ range, value.var = c("NoR", "AGI"))
   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:                   183454            1035373                 319540         2588950187             2396550000
2:                   241199            4272260                4826042        10682786130            36195315000
3:                   249506            1124098                1959866         2810807049            14698995000

, который воспроизводит ожидаемый результат OP. Обратите внимание, что имена переменных vn - cr выполняется автоматически.


Агрегация и группировка могут выполняться при изменении формы

dcast(long, No_Adjusted_Gross_Income ~ range, sum, value.var = c("NoR", "AGI"))
   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:                   183454            1035373                 319540         2588950187             2396550000
2:                   241199            4272260                4826042        10682786130            36195315000
3:                   249506            1124098                1959866         2810807049            14698995000

или

dcast(long, No_Adjusted_Gross_Income ~ ., sum, value.var = c("NoR", "AGI"))
   No_Adjusted_Gross_Income     NoR         AGI
1:                   183454 1354913  4985500187
2:                   241199 9098302 46878101130
3:                   249506 3083964 17509802049

В качестве альтернативы агрегация и группировка могут выполняться в длинном формате:

long[, lapply(.SD, sum), .SDcols = c("NoR", "AGI"), by = No_Adjusted_Gross_Income]
   No_Adjusted_Gross_Income     NoR         AGI
1:                   183454 1354913  4985500187
2:                   241199 9098302 46878101130
3:                   249506 3083964 17509802049
1 голос
/ 25 мая 2020

Это должно работать .. lapply() не требуется

library( data.table )
setDT( DF )
DF[, (var) := as.data.table ( t( t( DF[, 2:3] ) * val ) ) ][]


#    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:                   183454            1035373                 319540         2588950187             2396550000
# 2:                   241199            4272260                4826042        10682786130            36195315000
# 3:                   249506            1124098                1959866         2810807049            14698995000
...