将数据帧的每一列乘以向量的最有效方法是什么?
例如,数据框 ( df) 具有以下列 ( col1, col2, col3, col4),向量 ( v) 具有以下元素 ( v1,v2,v3)。
我希望输出是: col2*v1, col3*v2, col4*v3
我一直在尝试,df[c(2:4)] * c(v1,v2,v3)但似乎向量的元素没有乘以每列的每一行。
您可以尝试(使用df和v来自理查德斯克里文的回答):
df[-1] <- t(t(df[-1]) * v)
df
# a x y z
# 1 a 5 40 105
# 2 b 10 50 120
# 3 c 15 60 135
Run Code Online (Sandbox Code Playgroud)
当您将矩阵乘以向量时,它会按列相乘。由于您想将行乘以向量,因此我们df[-1]使用转置t,乘以v,然后使用 转回t。
似乎这种方法在基准测试方面比该Map方法略有优势,并且比sweep:
library(microbenchmark)
rscriven <- function(df, v) cbind(df[1], Map(`*`, df[-1], v))
josilber <- function(df, v) cbind(df[1], t(t(df[-1]) * v))
dardisco <- function(df, v) cbind(df[1], sweep(df[-1], MARGIN=2, STATS=v, FUN="*"))
df2 <- cbind(data.frame(rep("a", 1000)), matrix(rnorm(100000), nrow=1000))
v2 <- rnorm(100)
all.equal(rscriven(df2, v2), josilber(df2, v2))
# [1] TRUE
all.equal(rscriven(df2, v2), dardisco(df2, v2))
# [1] TRUE
microbenchmark(rscriven(df2, v2), josilber(df2, v2), dardisco(df2, v2))
# Unit: milliseconds
# expr min lq median uq max neval
# rscriven(df2, v2) 5.276458 5.378436 5.451041 5.587644 9.470207 100
# josilber(df2, v2) 2.545144 2.753363 3.099589 3.704077 8.955193 100
# dardisco(df2, v2) 11.647147 12.761184 14.196678 16.581004 132.428972 100
Run Code Online (Sandbox Code Playgroud)
感谢@thelatemail 指出,Map对于 100 倍大的数据帧,该方法要快得多:
df2 <- cbind(data.frame(rep("a", 10000)), matrix(rnorm(10000000), nrow=10000))
v2 <- rnorm(1000)
microbenchmark(rscriven(df2, v2), josilber(df2, v2), dardisco(df2, v2))
# Unit: milliseconds
# expr min lq median uq max neval
# rscriven(df2, v2) 75.74051 90.20161 97.08931 115.7789 259.0855 100
# josilber(df2, v2) 340.72774 388.17046 498.26836 514.5923 623.4020 100
# dardisco(df2, v2) 928.81128 1041.34497 1156.39293 1271.4758 1506.0348 100
Run Code Online (Sandbox Code Playgroud)
似乎您需要进行基准测试以确定哪种方法对您的应用程序最快。