R умножить 2 кадра данных на основе метки фактора

У меня есть 2 фрейма данных. Первый имеет несколько строк, второй — одну строку. Мне нужно умножить каждую строку первого кадра на одну строку второго кадра. Первый кадр данных называется Costs и выглядит так:

Pounds, Zone.A, Zone.B, Zone.C, Zone.D, Zone.E
5,      10.0,   20.0,   1.00,   23.0,   34.5
10,     20.0,   40.0,   10.0,   34.5,   54.0
15,     40.0,   100.0,  100.0,  67.8,   98.2

Вторая таблица называется Weights и выглядит так:

Zone.A, Zone.B, Zone.C
0.5,    0.3,    0.2

Когда я умножаю их, если в таблице Weights отсутствует множитель, мне нужно, чтобы соответствующий множитель в таблице Costs стал 0.0. Результат, который я хотел бы, будет:

Pounds, Zone.A, Zone.B, Zone.C, Zone.D, Zone.E
5,      5.0,    6.00,   0.20,   0.0,    0.0
10,     10.0,   12.0,   2.00,   0.0,    0.0
15,     20.0,   30.0,   20.0,   0.0,    0.0

После этого я суммирую столбцы Zone.* по строкам для общего результата, который я уже знаю, как это сделать, но если я могу пропустить промежуточный шаг, это было бы здорово. Конечным результатом, который я ищу, будет:

Pounds, Total
5,      11.2
10,     24.0
15,     70.0

Я не уверен, как это сделать с фреймами данных, которые не имеют совпадающих размеров, поэтому любая помощь приветствуется.


person Matthew Crews    schedule 13.02.2014    source источник


Ответы (3)


Вот вариант:

missing.names <- names(Costs[-1])[!names(Costs[-1]) %in% names(Weights)]
Weights[, missing.names] <- do.call(data.frame, as.list(rep(0, length(missing.names))))
cbind(
  Pounds=Costs$Pounds, 
  Total=rowSums(t(t(as.matrix(Costs[2:ncol(Costs)])) * unlist(Weights2[names(Costs[-1])])))
)
#      Pounds Total
# [1,]      5  11.2
# [2,]     10  24.0
# [3,]     15  70.0
person BrodieG    schedule 13.02.2014
comment
Благодарю за ваш ответ. Я уверен, что мне также понадобится это промежуточное состояние, но в этом случае мне в конечном итоге просто нужно было суммировать столбцы. Однако, спасибо! - person Matthew Crews; 14.02.2014

Еще одна возможность:

library(reshape2)
d1 <- melt(Costs, id.var = "Pounds")
d2 <- melt(Weights)

d1 <- merge(d1, d2, by = "variable", all.x = TRUE)
d1$Total <- with(d1, value.x * value.y) 

aggregate(Total ~ Pounds, data = d1, sum, na.rm = TRUE)

#   Pounds Total
# 1      5  11.2
# 2     10  24.0
# 3     15  70.0
person Henrik    schedule 13.02.2014

person    schedule
comment
Это строго не делает то, что просит ОП, хотя я думаю, что результат тот же, и так намного проще (+1). - person BrodieG; 14.02.2014
comment
@BrodieG правда .. хотя я не вижу причин, по которым вы хотели бы / должны добавлять нули к весам, если вы просто собираетесь их суммировать. +1 и вам за точное следование ОП :) - person Jake Burkhead; 14.02.2014