Thomas
Thomas

Reputation: 2534

How to apply operation and sum over columns in R?

I want to apply some operations to the values in a number of columns, and then sum the results of each row across columns. I can do this using:

x <- data.frame(sample=1:3, a=4:6, b=7:9)
x$a2 <- x$a^2
x$b2 <- x$b^2
x$result <- x$a2 + x$b2

but this will become arduous with many columns, and I'm wondering if anyone can suggest a simpler way. Note that the dataframe contains other columns that I do not want to include in the calculation (in this example, column sample is not to be included).

Many thanks!

Upvotes: 3

Views: 12402

Answers (6)

Michael J. Chapman
Michael J. Chapman

Reputation: 11

I want to come at this one from a "no extensions" R POV.

It's important to remember what kind of data structure you are working with. Data frames are actually lists of vectors--each column is itself a vector. So you can you the handy-dandy lapply function to apply a function to the desired column in the list/data frame.

I'm going to define a function as the square as you have above, but of course this can be any function of any complexity (so long as it takes a vector as an input and returns a vector of the same length. If it doesn't, it won't fit into the original data.frame!

The steps below are extra pedantic to show each little bit, but obviously it can be compressed into one or two steps. Note that I only retain the sum of the squares of each column, given that you might want to save space in memory if you are working with lots and lots of data.

  • create data; define the function

  • grab the columns you want as a separate (temporary) data.frame

  • apply the function to the data.frame/list you just created.

  • lapply returns a list, so if you intend to retain it seperately make it a temporary data.frame. This is not necessary.

  • calculate the sums of the rows of the temporary data.frame and append it as a new column in x.

  • remove the temp data.table.

Code:

x <- data.frame(sample=1:3, a=4:6, b=7:9); square <- function(x) x^2 #step 1

x[2:3] #Step 2

temp <- data.frame(lapply(x[2:3], square)) #step 3 and step 4

x$squareRowSums <- rowSums(temp) #step 5

rm(temp) #step 6

Upvotes: 1

Cath
Cath

Reputation: 24074

If you want to apply a function named somefunction to some of the columns, whose indices or colnames are in the vector col_indices, and then sum the results, you can do :

# if somefunction can be vectorized :
x$results<-apply(x[,col_indices],1,function(x) sum(somefunction(x)))

# if not :
x$results<-apply(x[,col_indices],1,function(x) sum(sapply(x,somefunction)))

Upvotes: 1

cdeterman
cdeterman

Reputation: 19950

I would simply subset the columns of interest and apply everything directly on the matrix using the rowSums function.

x <- data.frame(sample=1:3, a=4:6, b=7:9)

# put column indices and apply your function
x$result <- rowSums(x[,c(2,3)]^2)

This of course assumes your function is vectorized. If not, you would need to use some apply variation (which you are seeing many of). That said, you can still use rowSums if you find it useful like so. Note, I use sapply which also returns a matrix.

# random custom function
myfun <- function(x){
    return(x^2 + 3)
}

rowSums(sapply(x[,c(2,3)], myfun))

Upvotes: 9

Fedorenko Kristina
Fedorenko Kristina

Reputation: 2767

You can use apply function. And get those columns that you need with c(i1,i2,..,etc).

apply(( x[ , c(2, 3) ])^2, 1 ,sum )

Upvotes: 1

johannes
johannes

Reputation: 14413

Here is an other apply solution

cols <- c("a", "b")
x <- data.frame(sample=1:3, a=4:6, b=7:9)
x$result <- apply(x[, cols], 1, function(x) sum(x^2))

Upvotes: 0

Marat Talipov
Marat Talipov

Reputation: 13304

I would suggest to convert the data set into the 'long' format, group it by sample, and then calculate the result. Here is the solution using data.table:

library(data.table)
melt(setDT(x),id.vars = 'sample')[,sum(value^2),by=sample]
#   sample  V1
#1:      1  65
#2:      2  89
#3:      3 117

You can easily replace value^2 by any function you want.

Upvotes: 1

Related Questions