2014-11-24 2 views
6

vorrei aggiungere una colonna al mio data.frame in R che contengono somme delle righe e dei prodotti Considerare seguenti frame di daticalcolare somma fila e prodotto in data.frame

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

voglio ottenere le seguenti

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

ho cercato

sum = apply(ages,1,add) 

ma mi dà un vettore riga. Qualcuno può mostrarmi un comando efficiente per sommare e prodotto e aggiungerli al frame originale come mostrato sopra?

risposta

13

Prova

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 

O

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 

Un'altra opzione sarebbe quella di utilizzare rowProds da matrixStats

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

Se si utilizza 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 
+0

Can y o per favore mi consigli cosa '' 'Riduci (' * ', df)' '' fa? –

+0

@Khurram Majeed È simile a 'Riduci (' * ', as.list (df))'. Poiché 'data.frame' è un' elenco', non è necessario usare 'as.list'. moltiplica ogni elemento nelle posizioni corrette come la 1a riga, la 2a riga, ecc. – akrun

3

Un altro approccio.

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 
+0

Dovresti dimostrare come usare 'lapply' in congiunzione con' .SD' e '.SDcols'. – Roland

+1

@Roland, non pensare che ci sia un bisogno in 'lapply' o' .SDcols' qui, dovrebbe aver appena fatto qualcosa come 'setDT (df) [,": = "(sum = rowSums (.SD), prod = Reduce ("*", .SD))] ' –

+0

Ho aggiunto una soluzione con' .SD'. Non vedo come 'lapply' possa aiutare qui. – djhurio

1

seguito può anche essere fatto, ma i nomi delle colonne devono essere inseriti:

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 

Con data.table, un'altra forma può essere:

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 

Una versione più semplice è suggerita da @ David Arenberg nei commenti:

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

Mi chiedo se potessi semplicemente assegnare per riferimento invece di usare 'cbind' ... Qualcosa come' dt [, ": =" (somma = x + y + z, prodotto = x * y * z)] 'forse? –

+0

Non ero a conoscenza di questa versione più semplice. – rnso