26

dfデータ フレームを vectorで乗算しようとしているvため、積はデータ フレームであり、i-th 行は で与えられ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

もっとRスタイルのアプローチ(そして非常に単純なもの)が必要だと確信していますが、何も思い浮かびません。私も次のようなことを試しました

apply(df, MARGIN=1, function(x) x*v)

それでも、次のような読み取り不可能な構造as.data.frame(t(.))が必要です。
ここで効率的でエレガントな回避策を見つけるにはどうすればよいですか?

4

6 に答える 6

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

Arun がコメントで指摘しているようにset、パッケージの関数を使用data.tableして、このインプレース変更をdata.frame同様に行うこともできます。

for (i in seq_along(df))
  set(df, j = i, value = df[[i]] * v[i])

もちろん、これは にも機能しdata.table、列の数が多い場合は大幅に高速になる可能性があります。

于 2013-08-22T16:37:13.047 に答える
8

ベクトルと行列を結合できる言語では、ある時点で、行列が行優先か列優先かを決定する必要があります。理由:

> df * v
  A  B
1 0  4
2 4  0
3 0  8
4 8  0
5 0 12

これは、R が最初に列を下に操作するためです。二重転置のトリックを行うと、これが覆されます。vこれがあなたの知っていることを説明しているだけなら申し訳ありませんが、同じサイズの行列に明示的に展開する以外に、それを行う別の方法はわかりません。

または、あまり R スタイルではないコードを R スタイルのものにラップする素敵な関数を作成します。

于 2013-08-22T14:22:02.683 に答える
4

どうしたの

t(apply(df, 1, function(x)x*v))

?

于 2013-08-22T14:24:42.957 に答える