我正在尝试将数据帧乘以df向量v,以便产品是数据框,其中i第 - 行由下式给出df[i,]*v.我可以这样做,例如,通过
df <- data.frame(A=1:5, B=2:6); v <- c(0,2)
as.data.frame(t(t(df) * v))
A B
1 0 4
2 0 6
3 0 8
4 0 10
5 0 12
Run Code Online (Sandbox Code Playgroud)
我确信必须有更多R风格的方法(而且非常简单!),但没有任何想法.我甚至尝试过类似的东西
apply(df, MARGIN=1, function(x) x*v)
Run Code Online (Sandbox Code Playgroud)
但仍然as.data.frame(t(.))需要不可读的结构.
如何在这里找到高效优雅的解决方法?
nog*_*pes 27
这也有效:
data.frame(mapply(`*`,df,v))
Run Code Online (Sandbox Code Playgroud)
在该解决方案,您正在利用的事实,data.frame是一个类型的list,所以你可以遍历的两个元素df,并v在同一时间mapply.
不幸的是,你可以输出的内容有限mapply:简单list或者a matrix.如果您的数据很大,这可能会更有效:
data.frame(mapply(`*`,df,v,SIMPLIFY=FALSE))
Run Code Online (Sandbox Code Playgroud)
因为它会将其转换为a list,转换为a更有效data.frame.
edd*_*ddi 12
如果你正在寻找速度和记忆效率 - data.table救援:
library(data.table)
dt = data.table(df)
for (i in seq_along(dt))
dt[, (i) := dt[[i]] * v[i]]
eddi = function(dt) { for (i in seq_along(dt)) dt[, (i) := dt[[i]] * v[i]] }
arun = function(df) { df * matrix(v, ncol=ncol(df), nrow=nrow(df), byrow=TRUE) }
nograpes = function(df) { data.frame(mapply(`*`,df,v,SIMPLIFY=FALSE)) }
N = 1e6
dt = data.table(A = rnorm(N), B = rnorm(N))
v = c(0,2)
microbenchmark(eddi(copy(dt)), arun(copy(dt)), nograpes(copy(dt)), times = 10)
#Unit: milliseconds
# expr min lq mean median uq max neval
# eddi(copy(dt)) 23.01106 24.31192 26.47132 24.50675 28.87794 34.28403 10
# arun(copy(dt)) 337.79885 363.72081 450.93933 433.21176 516.56839 644.70103 10
# nograpes(copy(dt)) 19.44873 24.30791 36.53445 26.00760 38.09078 95.41124 10
Run Code Online (Sandbox Code Playgroud)
正如Arun在评论中指出的那样,也可以使用包中的set函数data.table对其进行就地修改data.frame:
for (i in seq_along(df))
set(df, j = i, value = df[[i]] * v[i])
Run Code Online (Sandbox Code Playgroud)
这当然也适用于data.table,如果列数很大,可能会明显更快.
允许您将向量与矩阵组合在一起的语言必须在某些时候做出决定矩阵是行主要还是列主要有序.原因:
> df * v
A B
1 0 4
2 4 0
3 0 8
4 8 0
5 0 12
Run Code Online (Sandbox Code Playgroud)
是因为R首先按列操作.做双重转置技巧颠覆了这一点.对不起,如果这只是解释你所知道的,但我不知道另一种方法,除了明确扩展v到相同大小的矩阵.
或者编写一个很好的函数,将非R风格的代码包装成R-stylish的东西.
| 归档时间: |
|
| 查看次数: |
24749 次 |
| 最近记录: |