1

I am trying to find the most efficient/shortest/prettiest solution to multiplying an array with another array. The arrays have different dimensions.

I want to multiply array consumption (dim = c(4, 5, 4)) with the array emissionFactors which is dim = c(1, 5, 4). I want one column value in emissionFactors to affect the whole column in consumption, per dimension. The result should be in the same array format and dimensions as consumption. All necessary code is provided here:

Right now I have a for loop which does the job, but I would like to get rid of it. I tried to use sapply to find a shorter/prettier solution to this problem but I could not get it any better than before.

Can this multiplying be done in shorter form, yet retaining its readability?

# needed vars
decades <- c("2020", "2030", "2040", "2050")
energyTypes <- c("Wood", "Fossils", "Ambient energy", "District heating",
                 "Electricity")
housingTypes <- c("Detached houses", "Terraced houses", 
                  "Residential blocks of flats", "Service buildings")

# consumption, array to be multiplied
consumption <- array(0, dim = c(4, 5, 4), dimnames = list(housingTypes, energyTypes, decades))
consumption[1, , 1] <- c(11385, 3148, 4958, 2629, 9607)
consumption[2, , 1] <- c(126, 186, 591, 3105, 1385)
consumption[3, , 1] <- c(47, 543, 81, 13635, 1136)
consumption[4, , 1] <- c(874, 3273, 183, 11902, 2106)
consumption[1, , 2] <- c(7447, 1463, 7114, 1645, 7253)
consumption[2, , 2] <- c(80, 0, 824, 2174, 1132)
consumption[3, , 2] <- c(0, 0, 836, 10355, 810)
consumption[4, , 2] <- c(1085, 1460, 953, 9027, 1810)
consumption[1, , 3] <- c(6256, 295, 7880, 639, 5323)
consumption[2, , 3] <- c(73, 0, 878, 1594, 861)
consumption[3, , 3] <- c(0, 0, 1180, 7767, 686)
consumption[4, , 3] <- c(919, 434, 1788, 6870, 1612)
consumption[1, , 4] <- c(4677, 0, 7686, 131, 4199)
consumption[2, , 4] <- c(53, 0, 811, 1221, 650)
consumption[3, , 4] <- c(0, 0, 1179, 6082, 435)
consumption[4, , 4] <- c(435, 3, 2249, 5328, 1260)

# emissionFactors is the array to multiply with
emissionFactors <- array(0, dim = c(1, 5, 4), dimnames = list("kg", energyTypes, decades))
emissionFactors[1, , 1] <- c(0, 263, 0, 160, 65)
emissionFactors[1, , 2] <- c(0, 263, 0, 76, 31)
emissionFactors[1, , 3] <- c(0, 263, 0, 64, 24)
emissionFactors[1, , 4] <- c(0, 263, 0, 45, 12)

# this array will be populated with the multiplied data from consumption * emissionFactors
emissions <- array(0, dim = c(4, 5, 4), dimnames = list(housingTypes, energyTypes, decades))

# Original version of the multiplying, has an undesired for loop
for (decade in 1:length(decades)) {

  emissions[, , decade] <- 
    consumption[, , decade] %*%
    diag(emissionFactors[, , decade])
}

# An further attempt, not any prettier. I thought one of the functions in the apply family would do the job but I can't get apply to work the way I would want
emissions2 <- sapply(1:dim(consumption)[3],
                     function(i) 
                       consumption[, , i] %*% 
                       diag(emissionFactors[, , i]))
emissions2 <- array(emissions2,
                    c(4, 5, 4),
                    dimnames = list(housingTypes, energyTypes, decades))

Thank you for any advice you might have.

2 Answers 2

1

Repeat the index in the first dimension 4 times.

n <- dim(consumption)[1] # 4
result <- consumption * emissionFactors[rep(1, n),, ]
identical(result, emissions)
## [1] TRUE
Sign up to request clarification or add additional context in comments.

Comments

1

Use option simplify="array".

sapply(1:length(decades), function(i) 
  `colnames<-`(consumption[, , i] %*% diag(emissionFactors[, , i]),
               colnames(consumption)), simplify="array")
# , , 1
# 
#                             Wood Fossils Ambient energy District heating Electricity
# Detached houses                0  827924              0           420640      624455
# Terraced houses                0   48918              0           496800       90025
# Residential blocks of flats    0  142809              0          2181600       73840
# Service buildings              0  860799              0          1904320      136890
# 
# , , 2
# 
#                             Wood Fossils Ambient energy District heating Electricity
# Detached houses                0  384769              0           125020      224843
# Terraced houses                0       0              0           165224       35092
# Residential blocks of flats    0       0              0           786980       25110
# Service buildings              0  383980              0           686052       56110
# 
# , , 3
# 
#                             Wood Fossils Ambient energy District heating Electricity
# Detached houses                0   77585              0            40896      127752
# Terraced houses                0       0              0           102016       20664
# Residential blocks of flats    0       0              0           497088       16464
# Service buildings              0  114142              0           439680       38688
# 
# , , 4
# 
#                             Wood Fossils Ambient energy District heating Electricity
# Detached houses                0       0              0             5895       50388
# Terraced houses                0       0              0            54945        7800
# Residential blocks of flats    0       0              0           273690        5220
# Service buildings              0     789              0           239760       15120

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.