user6055028
user6055028

Reputation:

R - divide/add to all columns in data frame values from vector

I have a vector x,y and data frame df such that

NCOL(x) = NCOL(y) = ncol(df).

I would like to divide each columns (all rows) by vector x (it means: all values in column one of df by the fist values in vector x, second column (all values) by second column (one value) of vector x.

The same situation for adding vector y to columns (the same way).

Could you help me do it in elegant way ?

Upvotes: 4

Views: 465

Answers (2)

bgoldst
bgoldst

Reputation: 35314

An alternative is to transpose, perform the operations taking advantage of automatic recycling of the short vector operands, and then transpose again to return to the original transposition. This solution results in a matrix rather than a data.frame, which may not be desirable, although it can be argued that since you're performing a numerical computation on every cell of the input, it's more appropriate to store it as a numeric matrix.

Stealing akrun's data for an example:

df <- as.data.frame(matrix(1:25,5L,5L));
x <- 1:5;
y <- 6:10;
t(t(df)/x + y);
##      V1   V2       V3    V4   V5
## [1,]  7 10.0 11.66667 13.00 14.2
## [2,]  8 10.5 12.00000 13.25 14.4
## [3,]  9 11.0 12.33333 13.50 14.6
## [4,] 10 11.5 12.66667 13.75 14.8
## [5,] 11 12.0 13.00000 14.00 15.0

This solution seems to have a performance benefit:

library(microbenchmark);
akrun <- function() df/x[col(df)] + y[col(df)];
bgoldst <- function() t(t(df)/x + y);
identical(as.data.frame(bgoldst()),akrun());
## [1] TRUE
identical(bgoldst(),as.matrix(akrun()));
## [1] TRUE
identical(bgoldst(),akrun());
## [1] FALSE
microbenchmark(akrun(),bgoldst(),times=1000L);
## Unit: microseconds
##       expr     min       lq      mean   median      uq      max neval
##    akrun() 812.542 867.9235 930.60749 894.6515 922.235 2395.288  1000
##  bgoldst()  50.036  58.5890  68.82336  67.1420  71.846 1417.672  1000

I've given akrun +1 for my thievery.

Upvotes: 1

akrun
akrun

Reputation: 887128

We can replicate 'x' and then divide the 'df'

df/x[col(df)]

If we need to add 'y'

(df/x[col(df)]) + y[col(df)]

data

df <- as.data.frame(matrix(1:25, 5, 5))
x <- 1:5
y <- 6:10

Upvotes: 3

Related Questions