Costs <- read.table(text = "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", header = TRUE, sep = ",")
Weights <- read.table(text = "Zone.A, Zone.B, Zone.C
0.5, 0.3, 0.2", header = TRUE, sep = ",")
CostsMat <- as.matrix(Costs[names(Weights)])
total <- CostsMat %*% matrix(unlist(Weights), ncol = 1)
data.frame(Pounds = Costs$Pounds, Total = total)
## Pounds Total
## 1 5 11.2
## 2 10 24.0
## 3 15 70.0
R multiply 2 dataframes based on factor label
Pergunta
I have 2 data frames. The first has multiple rows the second has a single row. I need to multiply each row of the first frame by the single row of the second frame. The first dataframe is called Costs
and looks like this:
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
The second table is named Weights
and looks like this:
Zone.A, Zone.B, Zone.C
0.5, 0.3, 0.2
When I multiply them if there is a missing factor in the Weights
table I need the corresponding factor in the Costs
table needs to become 0.0
. The result that I would want would be:
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
After that I will sum the Zone.* columns by row for the total which I already know how to do but if I can skip the intermediate step that would be great. The final result I'm looking for would be:
Pounds, Total
5, 11.2
10, 24.0
15, 70.0
I'm not sure how to do this with dataframes which do not have matching dimensions so any help is greatly appreciated.
Solução
Outras dicas
Here is an option:
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
Yet another possibility:
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