Условно умножить значения на основе имен - PullRequest
5 голосов
/ 11 ноября 2019

У меня есть один фрейм данных, что-то вроде:

d <-
  data.frame(
    col1 = c(7, 8, 9),
    col2 = c(12, 7, 0),
    col3 = c(1, 2, 3)
  )

и вектор с числами

coefs <-
  c(
    col1  = 4,
    col2  = 6
  )

, что мне нужно сделать, это если имя столбца в моем df равно векторному столбцутогда я хотел бы умножить это. Если имя столбца другое, отсутствует или не совпадает, то оно должно остаться прежним.

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

result <-
  data.frame(
    col1 = c(28, 32, 36),
    col2 = c(72, 42, 0),
    col3 - c(1, 2, 3)
  )

Iдумаю, что лучшим подходом было бы использовать mutate_if, но я не уверен, как сопоставлять имена столбцов.

Ответы [ 3 ]

6 голосов
/ 11 ноября 2019

Вы можете сделать это непосредственно в базе R

d[names(coefs)] <- d[names(coefs)] * as.list(coefs)
d

#  col1 col2 col3
#1   28   72    1
#2   32   42    2
#3   36    0    3
1 голос
/ 11 ноября 2019

Вы также можете использовать sweep() из base R:

d[names(coefs)] <- sweep(d[names(coefs)], 2, FUN = "*", coefs)

  col1 col2 col3
1   28   72    1
2   32   42    2
3   36    0    3

В общем, dplyr не очень подходит для этих операций, подобных развертке. Это потому, что он не применяет одно значение на столбец, как можно было бы ожидать, а перерабатывает значения. Чтобы проиллюстрировать это:

d %>%
 mutate_at(vars(names(coefs)), ~ . * coefs)

  col1 col2 col3
1  112  288    1
2  192  252    2
3  144    0    3

Вы видите, что первый столбец 28 * 4, 32 * 6, а затем 36 * 4.

0 голосов
/ 11 ноября 2019

Вот хорошая вещь для цикла, чтобы сделать тяжелую работу:

for (i in colnames(d)) {
  if (any(names(coefs) %in% i)) {
    d[, i] <- d[, i] * coefs[i]
  }
}

> d
  col1 col2 col3
1   28   72    1
2   32   42    2
3   36    0    3
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...