2

私は約 6 か月前に R を使い始め、R で少し経験を積んできました。最近、マトリックス内のサブセットに関する問題に遭遇し、私が持っているソリューションをより効率的にするための支援を求めています。

私がやりたいことは次のとおりです。次のような行列と 2 つのベクトルがあるとします。

# matrix
a <- matrix(seq(1,100,by=1),10,10)
# vector (first column of matrix a)
b <- c(2,4,5,6,7,8)
# vector (column numbers of matrix a)
c <- c(5,3,1,4,6,2)

繰り返しますが、

  • ベクトルbは、行列の最初の列を参照しますa
  • ベクトルcは、行列の列番号を参照しますa

頂きたいですtmp99 <- a[b,c:8]。ただし、これを行うと、次の警告メッセージが表示されます。

Warning message:
In c:8 : numerical expression has 6 elements: only the 
        first used (index has to be scalar and not vector)

それで、ループとリストを使用して問題を回避しようとしましたが、必要な解決策が得られました。これよりも時間効率の良い解決策があると思います。私がこれまでに持っている解決策は次のとおりです。

a <- matrix(seq(1,100,by=1),10,10)
b <- c(2,4,5,6,7,8)
c <- c(5,3,1,4,6,2)
tmp <- list()
for (i in 1:length(b)) tmp[[i]] <- c(a[b[i],(c[i]:8)])
tmp99 <- t(sapply(tmp, '[', 1:max(sapply(tmp, length))))
tmp99[is.na(tmp99)] <- 0

私が知りたいのは、ループを使用して上記を達成することを避ける方法があるかどうかです。なぜなら、私の行列の次元は200000 x 200そうであり、これを頻繁に行う必要があるからです (私の問題でbc、コードの別の部分の一部として決定されます)したがって、絶対インデックス番号を使用することはできません)、同じためにかかる時間を短縮したいと思います。どんな助けでも大歓迎です。ありがとうございました。

4

3 に答える 3

2

このような、ある種のマトリックスインデックスソリューションを試すことができます。それが実際に速くなるかどうかは明らかではありません。小さなケースでは間違いなくそうなると思いますが、大きなケースでは、行列を作成してインデックスを作成することによるオーバーヘッドは、forループを実行するよりも長くかかる可能性があります。より良い答えを得るには、テストできるデータセットに類似したデータセットを作成します。

idx.in <- cbind(rep(b, 8-c+1), unlist(lapply(c, function(x) x:8)))
idx.out <- cbind(rep(seq_along(b), 8-c+1), unlist(lapply(c, function(x) 1:(8-x+1))))
tmp99 <- array(0, dim=apply(idx.out, 2, max))
tmp99[idx.out] <- a[idx.in]

これはマトリックスインデックス付きのバージョンですが、行ごとに個別に行われます。置き換えられる行と列の数によっては、これが高速になる場合があります。回避したいのはメモリ不足です。これは、メモリ内の各ステップのすべての詳細を同時に保持するわけではないため、forループが役立ちます。

out <- array(0, dim=c(length(b), 8-min(c)+1))
for(idx in seq_along(b)) {
  out[cbind(idx, 1:(8-c[idx]+1))] <- a[cbind(b[idx], c[idx]:8)]
}
out
于 2013-03-18T14:44:58.527 に答える
1

以下は、baseパッケージを使用してそれを行う1つの方法です。使用するより良い解決策があるかもしれませんがdata.table、以下の作品:)

a <- matrix(seq(1, 100, by = 1), 10, 10)
b <- c(2, 4, 5, 6, 7, 8)
c <- c(5, 3, 1, 4, 6, 2)

res <- t(sapply(X = mapply(FUN = function(b, c) expand.grid(b, seq(from = c, to = 8)), b, c, SIMPLIFY = FALSE), FUN = function(x) {
    c(a[as.matrix(x)], rep(0, 8 - nrow(x)))
}))

res
##      [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8]
## [1,]   42   52   62   72    0    0    0    0
## [2,]   24   34   44   54   64   74    0    0
## [3,]    5   15   25   35   45   55   65   75
## [4,]   36   46   56   66   76    0    0    0
## [5,]   57   67   77    0    0    0    0    0
## [6,]   18   28   38   48   58   68   78    0



# Let's break it down in multiple steps.

coordinates <- mapply(FUN = function(b, c) expand.grid(b, seq(from = c, to = 8)), b, c, SIMPLIFY = FALSE)

# below sapply subsets c using each element in coordinates and pads result with additional 0s such that total 8 elements are returned.

res <- sapply(X = coordinates, FUN = function(x) {
    c(a[as.matrix(x)], rep(0, 8 - nrow(x)))
})
res
##      [,1] [,2] [,3] [,4] [,5] [,6]
## [1,]   42   24    5   36   57   18
## [2,]   52   34   15   46   67   28
## [3,]   62   44   25   56   77   38
## [4,]   72   54   35   66    0   48
## [5,]    0   64   45   76    0   58
## [6,]    0   74   55    0    0   68
## [7,]    0    0   65    0    0   78
## [8,]    0    0   75    0    0    0


# you probably need result as traspose
res <- t(res)

res
##      [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8]
## [1,]   42   52   62   72    0    0    0    0
## [2,]   24   34   44   54   64   74    0    0
## [3,]    5   15   25   35   45   55   65   75
## [4,]   36   46   56   66   76    0    0    0
## [5,]   57   67   77    0    0    0    0    0
## [6,]   18   28   38   48   58   68   78    0
于 2013-03-18T14:42:35.973 に答える
0
tmp <- lapply(seq_len(length(b)),function(i) {
  res <- a[b[i],c[i]:8]
  res <- c(res,rep(0,c[i]-1))
  res
                                              })
tmp99 <- do.call("rbind",tmp)
#       [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8]
# [1,]   42   52   62   72    0    0    0    0
# [2,]   24   34   44   54   64   74    0    0
# [3,]    5   15   25   35   45   55   65   75
# [4,]   36   46   56   66   76    0    0    0
# [5,]   57   67   77    0    0    0    0    0
# [6,]   18   28   38   48   58   68   78    0
于 2013-03-18T14:59:46.287 に答える