Умножение набора значений в фрейме данных с помощью dplyr

#r #dplyr

#r #dplyr

Вопрос:

Итак, у меня есть фрейм данных следующим образом:

 ID    A  B  C
1    .3 .3 .4
2    .1 .5 .4
3    .7  0 .3
  

И у меня есть следующее:

 ID  VALUE
1      10
1       5
1     100
2      30
3      34
2      12
  

Я в основном хочу умножить my VALUE на my Df1 , чтобы получить эти переменные. Таким образом, для каждого экземпляра идентификатора используются соответствующие множители. Здесь требуется решение Dplyr.

Моя конечная цель:

 ID  VALUE     A   B     C
1      10     3   3     4
1       5   1.5 1.5     2 
1     100    30  30    40
2      30     3  15    12
3      34  23.8   0  10.2
2      12   1.2   6   4.8
  

РЕДАКТИРОВАТЬ: переменная ID является символом

Ответ №1:

Один из способов — объединить два ID , а затем умножить на те переменные, которые вы хотите.

 library(tibble)
library(dplyr)

df1 <- tribble(
  ~ID,    ~A,  ~B,  ~C,
  1,  .3, .3, .4,
  2,   .1, .5, .4,
  3,    .7,  0, .3
)

df2 <- tribble(
  ~ID,  ~VALUE,
  1,      10,
  1,       5,
  1,     100,
  2,      30,
  3,      34,
  2,      12
)

left_join(
  df2, df1, by = "ID"
) %>% 
  mutate_at(vars(A, B, C), ~VALUE*.)


# A tibble: 6 x 5
     ID VALUE     A     B     C
  <dbl> <dbl> <dbl> <dbl> <dbl>
1     1    10   3     3     4  
2     1     5   1.5   1.5   2  
3     1   100  30    30    40  
4     2    30   3    15    12  
5     3    34  23.8   0    10.2
6     2    12   1.2   6     4.8
  

Редактировать:

Чтобы изменить все переменные сразу, замените последний фрагмент кода на:

 left_join(
  df2, df1, by = "ID"
) %>% 
  mutate(across(-c(ID, VALUE), ~VALUE*.x))
  

Комментарии:

1. Обратите внимание, что mutate_at() и другие глаголы с областью действия заменяются dplyr . Рекомендуется использовать значение mutate across , как в mutate(across(c(A, B, C), ~ VALUE * .x))

2. Хорошо, это близко; однако мои данные содержат около 100 переменных, то есть больше, чем A, B и C.

3. @JoaoPedroMacalos спасибо за к вашему сведению, не знал

4. @JohnThomas вы могли бы использовать аккуратный выбор для этих 100 переменных. или другое решение будет включать некоторое длинное / широкое преобразование, чтобы упростить операцию

5. @JoaoPedroMacalos это почти работает, но everything() по-прежнему включает переменную ID, которая является символом, поэтому она не работает. По сути, он должен работать с каждой переменной, КРОМЕ ID, первого столбца и только символьной переменной

Ответ №2:

В базе R вы могли бы сделать:

 n <- ncol(df1)
A <- merge(df1, df2[c(1, rep(2, n-1))])
A[2:n] * A[(2:n)   n - 1]
     A    B    C
1  3.0  3.0  4.0
2  1.5  1.5  2.0
3 30.0 30.0 40.0
4  3.0 15.0 12.0
5  1.2  6.0  4.8
6 23.8  0.0 10.2
  

Ответ №3:

Мы можем использовать data.table

 library(data.table)
nm1 <- names(df1)[-1]
setDT(df2)[setDT(df1), (nm1) := lapply(mget(paste0("i.", nm1)),
             `*`, VALUE),on = .(ID)]
  

-вывод

 df2
#   ID VALUE    A    B    C
#1:  1    10  3.0  3.0  4.0
#2:  1     5  1.5  1.5  2.0
#3:  1   100 30.0 30.0 40.0
#4:  2    30  3.0 15.0 12.0
#5:  3    34 23.8  0.0 10.2
#6:  2    12  1.2  6.0  4.8