Repeatedly using ave to compute group tools in a data frame

The following code separately creates the group facilities x and y according to group . Suppose I have a series of variables for which the same operation is repeated.

How do you suggest continuing to get the same result with a single command? (I suppose you need to take tapply , but I'm not sure about that ..).

 x=seq(1,11,by=2); y=seq(2,12,by=2); group=rep(1:2, each=3) dat <- data.frame(cbind(group, x, y)) dat$m_x <- ave(dat$x, dat$group) dat$m_y <- ave(dat$y, dat$group) dat 

Thank you very much.

+3
source share
3 answers

Alternative solutions using data.table and plyr :

1) Using data.table

 require(data.table) dt <- data.table(dat, key="group") # Following @Matthew comment, edited: dt[, `:=`(m_x = mean(x), m_y = mean(y)), by=group] 

Output:

  group xy m_x m_y 1: 1 1 2 3 4 2: 1 3 4 3 4 3: 1 5 6 3 4 4: 2 7 8 9 10 5: 2 9 10 9 10 6: 2 11 12 9 10 

2) using plyr and convert:

 require(plyr) ddply(dat, .(group), transform, m_x=mean(x), m_y=mean(y)) 

output:

  group xy m_x m_y 1 1 1 2 3 4 2 1 3 4 3 4 3 1 5 6 3 4 4 2 7 8 9 10 5 2 9 10 9 10 6 2 11 12 9 10 

3) using plyr and numcolwise (note the reduced output):

 ddply(dat, .(group), numcolwise(mean)) 

Output:

  group xy 1 1 3 4 2 2 9 10 
+4
source

Assuming you have at most two columns, you should use apply to apply ave to each column in the matrix.

 x=seq(1,11,by=2); y=seq(2,12,by=2); group=rep(1:2, each=3) dat <- cbind(x, y) ave.dat <- apply(dat, 2, function(column) ave(column, group)) # xy # [1,] 1 2 # [2,] 3 4 # [3,] 5 6 # [4,] 7 8 # [5,] 9 10 # [6,] 11 12 
+3
source

You can also use aggregate ():

 dat2 <- data.frame(dat, aggregate(dat[,-1], by=list(dat$group), mean)[group, -1]) dat2 group xy x.1 y.1 1 1 1 2 3 4 1.1 1 3 4 3 4 1.2 1 5 6 3 4 2 2 7 8 9 10 2.1 2 9 10 9 10 2.2 2 11 12 9 10 row.names(dat2) <- rownames(dat) colnames(dat2) <- gsub("(.)\\.1", "m_\\1", colnames(dat2)) dat2 group xy m_x m_y 1 1 1 2 3 4 2 1 3 4 3 4 3 1 5 6 3 4 4 2 7 8 9 10 5 2 9 10 9 10 6 2 11 12 9 10 

If the variable names are more than one character, you will need to change the call to gsub ().

+1
source

Source: https://habr.com/ru/post/975788/


All Articles