Khurram Majeed
Khurram Majeed

Reputation: 2391

calculate row sum and product in data.frame

I would like to append a columns to my data.frame in R that contain row sums and products Consider following data frame

x    y     z
1    2     3
2    3     4
5    1     2

I want to get the following

x    y     z    sum    prod
1    2     3    6       6  
2    3     4    9       24 
5    1     2    8       10

I have tried

 sum = apply(ages,1,add)

but it gives me a row vector. Can some one please show me an efficient command to sum and product and append them to original data frame as shown above?

Upvotes: 15

Views: 50684

Answers (6)

ThomasIsCoding
ThomasIsCoding

Reputation: 101383

With base R, you can use Reduce like below

cbind(
    df,
    list2DF(
        lapply(
            c(sum = `+`, prod = `*`),
            \(op) Reduce(op, df)
        )
    )
)

which gives

  x y z sum prod
1 1 2 3   6    6
2 2 3 4   9   24
3 5 1 2   8   10

Data

df <- data.frame(x = c(1, 2, 5), y = c(2, 3, 1), z = c(3, 4, 2))

Upvotes: 0

noNameTed
noNameTed

Reputation: 307

Here is a quick way to do it using base R.

# create your example data frame
df <- data.frame(x=c(1,2,5), y=c(2,3,1), z=c(3,4,1))

# add the sum column
df$sum <- apply(df, MARGIN = 1, sum)

# add the product column (don't include the sum column from the last operation)
df$prod <- apply(df[,-4], MARGIN = 1, prod)

# print result to console
df

  x y z sum prod
1 1 2 3   6    6
2 2 3 4   9   24
3 5 1 1   7    5

Upvotes: 0

r.user.05apr
r.user.05apr

Reputation: 5456

Only a partial answer, but if all values are greater than or equal to 0, rowSums/rowsum can be used to calculate products:

df <- data.frame(x = c(1, 2, 5), y = c(2, 3, 1), z = c(3, 4, 2))

# custom row-product-function
my_rowprod <- function(x) exp(rowSums(log(x)))

df$prod <- my_rowprod(df)
df

The generic version is (including negatives):

my_rowprod_2 <- function(x) {
  sign <- ifelse((rowSums(x < 0) %% 2) == 1, -1, 1)
  prod <- exp(rowSums(log(abs(x)))) * sign
  prod
}
df$prod <- my_rowprod_2(df)
df

Upvotes: 3

rnso
rnso

Reputation: 24545

Following can also be done but column names need to be entered:

ddf$sum = with(ddf, x+y+z)
ddf$prod = with(ddf, x*y*z)
ddf
  x y z sum prod
1 1 2 3   6    6
2 2 3 4   9   24
3 5 1 2   8   10

With data.table, another form can be:

library(data.table)    
cbind(dt, dt[,list(sum=x+y+z, product=x*y*z),])
   x y z sum product
1: 1 2 3   6       6
2: 2 3 4   9      24
3: 5 1 2   8      10

A simpler version is suggested by @David Arenberg in comments:

dt[, ":="(sum = x+y+z, product = x*y*z)]

Upvotes: 4

djhurio
djhurio

Reputation: 5536

Another approach.

require(data.table)

# Create data
dt <- data.table(x = c(1,2,5), y = c(2,3,1), z = c(3,4,2))

# Create index
dt[, i := .I]

# Compute sum and prod
dt[, sum := sum(x, y, z), by = i]
dt[, prod := prod(x, y, z), by = i]
dt


# Compute sum and prod using .SD
dt[, c("sum", "prod") := NULL]
dt
dt[, sum := sum(.SD), by = i, .SDcols = c("x", "y", "z")]
dt[, prod := prod(.SD), by = i, .SDcols = c("x", "y", "z")]
dt


# Compute sum and prod using .SD and list
dt[, c("sum", "prod") := NULL]
dt
dt[, c("sum", "prod") := list(sum(.SD), prod(.SD)), by = i,
   .SDcols = c("x", "y", "z")]
dt


# Compute sum and prod using .SD and lapply
dt[, c("sum", "prod") := NULL]
dt
dt[, c("sum", "prod") := lapply(list(sum, prod), do.call, .SD), by = i,
   .SDcols = c("x", "y", "z")]
dt

Upvotes: 7

akrun
akrun

Reputation: 887128

Try

 transform(df, sum=rowSums(df), prod=x*y*z)
 #  x y z sum prod
 #1 1 2 3   6    6
 #2 2 3 4   9   24
 #3 5 1 2   8   10

Or

 transform(df, sum=rowSums(df), prod=Reduce(`*`, df))
 #   x y z sum prod
 #1 1 2 3   6    6
 #2 2 3 4   9   24
 #3 5 1 2   8   10

Another option would be to use rowProds from matrixStats

 library(matrixStats)
 transform(df, sum=rowSums(df), prod=rowProds(as.matrix(df)))

If you are using apply

 df[,c('sum', 'prod')] <-  t(apply(df, 1, FUN=function(x) c(sum(x), prod(x))))
 df
 #  x y z sum prod
 #1 1 2 3   6    6
 #2 2 3 4   9   24
 #3 5 1 2   8   10

Upvotes: 26

Related Questions