best way to apply across an xts object
You can use the function vapply. The help page of ?vapply says:


  vapply is similar to sapply, but has a pre-specified type of return
  value, so it can be safer (and sometimes faster) to use.


You can use

vapply(xz, function(col) col + 100, FUN.VALUE = numeric(nrow(xz))


The argument FUN.VALUE is used to tell the vapply what the function returns. Since all columns are numeric, the function returns a numeric vector of length nrow(xz) for each column of xz. Unfortunately, vapply does not preserve the dates of the xts object.

You can use the following command to generate a new object based on xz and replace all values with the matrix returned by vapply. This is very easy with the following command:

"[&lt;-"(xz, , vapply(xz, function(col) col + 100, FUN.VALUE = numeric(nrow(xz))))


The function "[&lt;-" copies the xz object and replaces all its values.

Alternatively, you can create a new xts object based on the matrix returned by vapply and the time information in your original xts object.

xts(vapply(xz, function(col) col + 100, FUN.VALUE = numeric(nrow(xz))),
    order.by = time(xz))




Now, we test the approaches:

vapFun &lt;- function() "[&lt;-"(xz, , vapply(xz, function(col) col + 100, 
                                        FUN.VALUE = numeric(nrow(xz))))

vapFun2 &lt;- function() xts(vapply(xz, function(col) col + 100, 
                                 FUN.VALUE = numeric(nrow(xz))),
                          order.by = time(xz))


library(microbenchmark)

op &lt;- microbenchmark(
  app = apFun(),
  sap = sapFun(), 
  mXf = mapXf(),
  vap = vapFun(),
  vap2 = vapFun2(),
  times = 1000L)

Unit: microseconds
 expr      min       lq   median       uq        max neval
  app 4066.612 4117.860 4167.324 4270.200 364484.879  1000
  sap 3337.001 3428.798 3463.680 3532.317   4310.336  1000
  mXf 1232.070 1263.531 1275.663 1295.014   2320.361  1000
  vap  984.732 1013.248 1022.726 1035.330 100172.130  1000
 vap2 1326.899 1368.562 1389.672 1428.608 126477.354  1000


As you can see, the approach with vapply and "[&lt;-" is the fastest one.



An important information: if the function you want to apply to each column is a mathematical operation, you can apply it to the whole xts object at once, e.g., xz + 100. This is considerably faster and returns an xts object, i.e., the dates are preserved.

simpleFun &lt;- function() xz + 100


op &lt;- microbenchmark(
  app = apFun(),
  sap = sapFun(), 
  mXf = mapXf(),
  vap = vapFun(),
  vap2 = vapFun2(),
  simple = simpleFun(),
  times = 1000L)

Unit: microseconds
   expr      min        lq   median        uq      max neval
    app 4063.972 4119.6995 4145.120 4243.7955 85454.87  1000
    sap 3347.558 3429.6725 3450.778 3515.3745 86508.52  1000
    mXf 1236.142 1267.2030 1276.455 1289.7095 84349.75  1000
    vap  992.792 1017.7425 1024.992 1033.7785 82275.26  1000
   vap2 1336.300 1372.8755 1390.553 1423.9875 83118.79  1000
 simple   92.770   98.4305  101.080  103.9995 81233.70  1000