Title: Faster way to multiplication in data frame
Tags: r
Question: I have a data frame (name t) like this
ID N com_a com_b com_c
A  3   1     0    0
A  5   0     1    0
B  1   1     0    0
B  1   0     1    0
B  4   0     0    1
B  4   1     0    0
I have try to do com_a*N com_b*N com_c*N
ID N com_a com_b com_c com_a_N com_b_N com_c_N
A  3   1     0    0       3       0       0
A  5   0     1    0       0       5       0
B  1   1     0    0       1       0       0
B  1   0     1    0       0       1       0
B  4   0     0    1       0       0       4
B  4   1     0    0       4       0       0
I use for-function, but it need many time how do i do the fast in the big data
for (i in 1:dim(t)[1]){
t$com_a_N[i]=t$com_a[i]*t$N[i]
t$com_b_N[i]=t$com_b[i]*t$N[i]
t$com_c_N[i]=t$com_c[i]*t$N[i]
Comment: @BenBolker the data is 1085350*70.

Comment: @BenBolker have to multiplication for columns 4:70. the variable N is in the 3 columns

Comment: @BenBolker i need to output 3*(4 to 70) columns

Comment: `t` is not a good name for a data set in R, as it's a stored function

Comment: how big is your data set?

Comment: are you doing the multiplication for columns 2:69?

Comment: so you need to expand the data frame out to 3*(1+66) columns?

Here is the accepted answer: t <- transform(t,
com_a_N=com_a*N,
com_b_N=com_b*N,
com_c_N=com_c*N)
should be much faster.  data.table solutions might be faster still.
Comment for this answer: I think `transform(t, com_a_N=ifelse(com_a, com_a, N))` could work too
Comment for this answer: yes.  I didn't look carefully enough at the structure of the data to see that the `com` columns were all binary ...

Here is another answer: You can use sweep for this
(st <- sweep(t[, 3:5], 1, t$N, "*"))
#  com_a com_b com_c
#1     3     0     0
#2     0     5     0
#3     1     0     0
#4     0     1     0
#5     0     0     4
#6     4     0     0
The new names can be created with paste and setNames, and you can add the new columns to the existing data.frame with cbind.  This will scale for any number of columns.
cbind(t, setNames(st, paste(names(st), "N", sep="_")))
#  ID N com_a com_b com_c com_a_N com_b_N com_c_N
#1  A 3     1     0     0       3       0       0
#2  A 5     0     1     0       0       5       0
#3  B 1     1     0     0       1       0       0
#4  B 1     0     1     0       0       1       0
#5  B 4     0     0     1       0       0       4
#6  B 4     1     0     0       4       0       0

Here is another answer: Another option with dplyr:
require(dplyr)
t <- mutate(t, com_a_N=com_a*N,
com_b_N=com_b*N,
com_c_N=com_c*N)
Comment for this answer: @G.Grothendieck, but why `group_by`?
Comment for this answer: Could also be formulated in dplyr like this: `t %>% group_by(ID, N) %>% mutate_each(funs(. * N))`
Comment for this answer: In that case `t %>% mutate_each(funs(. * N), vars = starts_with("com"))`
Comment for this answer: @BenBolker I haven't compared the performances. Just thought it might be another option to try since, as far as I understood, dplyr is in some cases faster than base R (I don't know if this applies in this case).
Comment for this answer: @BenBolker in that case my apologies for posting an answer that is not significantly different from one of the previous answers (yours in this case). Lack of knowledge on my side.
Comment for this answer: @G.Grothendieck wouldnt this mutate/overwrite the existing columns? I think the OP wanted to add new columns
Comment for this answer: I don't see any benefit to this over the `transform()` solution -- is `mutate` faster or otherwise different in a way that matters here ... ?
Comment for this answer: I don't actually think it'll make very much difference here (I think the big advantage of `dplyr` is over `plyr`, which is elegant but slow, not necessarily over base R).
Comment for this answer: actually, comment in R chat room suggests you may be right and I may be wrong: "the only issue is if the entire object is being copied to add the new columns. And mutate from dplyr shallow copies (and so does R 3.1.0), whereas transform in R versions prior to 3.1.0 would copy the entire object. So, if you've a large object( > 2GB) + R < 3.1.0, then you're more likely see a difference."

Here is another answer: Even faster using matrix multiplication:
cbind(dat,dat[,3:5]*dat$N)
Though you should set colnames after....
To avoid using explicit column index(not recommended) , you can use some grep  magic:
cbind(dat,dat[,grep('com',colnames(dat))]*dat$N)

Here is another answer: A data.table solution as proposed by @BenBolker
library(data.table)
setDT(t)[, c("com_a_N", "com_b_N", "com_c_N") := list(com_a*N, com_b*N, com_c*N)]
##    ID N com_a com_b com_c com_a_N com_b_N com_c_N
## 1:  A 3     1     0     0       3       0       0
## 2:  A 5     0     1     0       0       5       0
## 3:  B 1     1     0     0       1       0       0
## 4:  B 1     0     1     0       0       1       0
## 5:  B 4     0     0     1       0       0       4
## 6:  B 4     1     0     0       4       0       0
Comment for this answer: You can also use `.SD` along with `lapply` with `.SDcols`.. Maybe you could add that as well?
Comment for this answer: The LHS is the same (although you can use `paste` to generate them rather than typing it out), then `:=`, then RHS would have `lapply(.SD, ...)` instead of creating the list manually, then `.SDcols`. Want to try again? ;)
Comment for this answer: Hm, yes dint think of that. You're right. Perhaps better to leave it then until [this one](https://r-forge.r-project.org/tracker/index.php?func=detail&aid=5222&group_id=240&atid=975) is fixed..
Comment for this answer: @Arun, not sure how to that effectively, maybe you'd add this a separate answer or your edit? `setDT(t)[, lapply(.SD, function(x) x*N, N), .SDcols = c("com_a", "com_b", "com_c")]` didn't work
Comment for this answer: @Arun, The only way I could make it to work is `setDT(t)[, c("com_a_N", "com_b_N", "com_c_N") := lapply(.SD, function(x) x*N), .SDcols = c("com_a", "com_b", "com_c", "N")]` but this is essentially parsing 4 variables into 3. How can I make `lapply` recognize `N` without parsing it into `.SDcols`?

{'source': 'StackExchangeDataset', 'subset': 'stackoverflow.com', 'metadata': {'AnswerCount': 5, 'CommentCount': 7, 'ContentLicense': 'CC BY-SA 3.0', 'CreationDate': '2014:00:05/24/14', 'FavoriteCount': None, 'PostTypeId': 1, 'Tags': '<r>', 'Title': 'Faster way to multiplication in data frame', 'ViewCount': 327, 'id': 23848224, 'user_AboutMe': '', 'user_AccountId': 2663349.0, 'user_DisplayName': 'Vivian', 'user_Reputation': 299.0, 'user_Views': 57.0, 'user_id': 2302498.0}}