pApaAPPApapapa
pApaAPPApapapa

Reputation: 385

Using for loop within an if-statement in R

I have a problem, where I need to multiply estimated growth rates on base-numbers. The growth rates are stored in a matrix (see data example below) and so are the base-numbers. This itself is easy - the problem is that I have several growth rates for several types of entities behind the base-numbers.

set.seed(1223)
Typ1.rates <- c(1.1,1.2,0.9,1.4)
Typ2.rates <- c(1.4,5.2,1.9,0.4)
g.rates <- t(cbind(Typ1.rates, Typ2.rates))


x <- as.data.frame(matrix(rexp(16, rate=.2), ncol=4)*100)
x$Type <- c(1,1,1,2)

So if the type == 1 for a given row, I want to multiply the first observation with the first observation in Typ1.rates (that is [1,1]) and so on.

This is obvisously easy if I have two types of rates, but if I have 25 types, and large matrices/data frames, this becomes tough to do manually.

Anyone with a good way of doing this?

If any more explanation or data/code is needed, please let me know

EDIT:

Using the seed set above I hope to get the following matrix

                       V1           V2           V3            V4
1: 141.8580480 1149.9857213  303.4234747 1014.77951629
2: 770.1481988  407.0247813 1219.3383377  156.62140585
3: 554.1117304  983.2339648  239.1584652   50.52442765
4: 584.8300270 1207.7605414 2252.7680594   43.13052390

Upvotes: 2

Views: 106

Answers (3)

Pierre Chevallier
Pierre Chevallier

Reputation: 754

Summary

You can make conditions directly in the dataframe to assign new values like so:

x[x$Type == 1, ]

This will display all the x values that match ==1

What you need next is to use the rates you have added, so for example :

x[x$Type == 1, ] * Typ1.rates

Final code

Let's say you want to loop through all the types you have and use conditions, like so:

Typ1.rates <- c(1.1,1.2,0.9,1.4)
Typ2.rates <- c(1.4,5.2,1.9,0.4)
g.rates <- t(cbind(Typ1.rates, Typ1.rates))


x <- as.data.frame(matrix(rexp(16, rate=.2), ncol=4)*100)
x$Type <- c(1,1,1,2)

for(i in 1:nrow(g.rates)) {
    # We apply the change to the n-1 columns in order to prevent any change to the type column
    x[x$Type == i, 1:(ncol(x)-1) ] <- x[x$Type == i, 1:(ncol(x) -1) ] * as.list(g.rates[i,])
}

This should be pretty fast to be executed.

Upvotes: 1

joel.wilson
joel.wilson

Reputation: 8413

Either using a simple multiplication

set.seed(1223)
g.rates[x[, 5], ] * x[, -5]  # Note in your question you missed to include Typ2.rates 

Or using data.table

library(data.table)
setDT(x)[, .SD*g.rates[x$Type,] , .SDcols = paste0("V", 1:4)]
#        V1        V2        V3         V4
#1 141.8580 1149.9857  303.4235 1014.77952
#2 770.1482  407.0248 1219.3383  156.62141
#3 554.1117  983.2340  239.1585   50.52443
#4 584.8300 1207.7605 2252.7681   43.13052 

Upvotes: 5

akrun
akrun

Reputation: 887531

We can do this in base R

 do.call(rbind, Map(`*`, split(x[-5], x$Type), 
                 split(g.rates, row(g.rates))))
 #        V1       V2        V3        V4
 #1.1 141.8580 1341.650  303.4235 869.81101
 #1.2 840.1617  373.106 1896.7485 100.68519
 #1.3 453.3641  983.234  292.3048  50.52443
 #2   584.8300 1207.761 2252.7681  43.13052

Upvotes: 1

Related Questions