Mean of many subsets of a dataframe
Here is a proposal for a different approach that doesn't use a for loop and has some simplifications.

First, an example data frame:

dat &lt;- data.frame(a1 = 9:11, a2 = 2:4, a3 = 3:5,
                  b1 = 4:6, b2 = 5:7, b3 = 1:3)
#   a1 a2 a3 b1 b2 b3
# 1  1  2  3  4  5  6
# 2  2  3  4  5  6  7
# 3  3  4  5  6  7  8


Now, we set the number of columns per group:

# number of columns per group (1-3, 4-6)
n &lt;- 3


Based on this information, some necessary information can be calculated:

# number of groups
n_grp &lt;- ncol(dat) / n
# 2

# column indices (one vector per group)
idx_grp &lt;- split(seq(dat), rep(seq(n_grp), each = n))
# $`1`
# [1] 2 3 4
#
# $`2`
# [1] 5 6 7


In the next step, lapply is used to calculate the row means of each group. This is much more convenient with the rowMeans function.

# calculate the row means for all groups
res &lt;- lapply(idx_grp, function(i) {
    # subset of the data frame
    tmp &lt;- dat[i]
    # calculate row means
    rowMeans(tmp, na.rm = TRUE)
})
# $`1`
# [1] 4.666667 5.666667 6.666667
#
# $`2`
# [1] 3.333333 4.333333 5.333333


The command above returns a list. It can be transformed into a data frame:

# transform list into a data frame
dat2 &lt;- as.data.frame(res)
#         X1       X2
# 1 4.666667 3.333333
# 2 5.666667 4.333333
# 3 6.666667 5.333333


In order to set the column names of the new data frame, we first have to extract the column names of the groups' first columns.

# extract names of first column of each group
names_frst &lt;- names(dat)[sapply(idx_grp, "[", 1)]
# [1] "a1" "b1"


Now, these names are used for the new data frame:

# modify column names of new data frame
names(dat2) &lt;- names_frst
#         a1       b1
# 1 4.666667 3.333333
# 2 5.666667 4.333333
# 3 6.666667 5.333333


Done.