2

~~~~~~~~~更新-ありがとう!元の質問ではもっと具体的にすべきだった。ポートフォリオ最適化プログラムで使用する割り当てテーブルを作成しようとしています。したがって、列は有価証券になり、各行は異なる割り当てになります。各行の合計は1(または100%)にする必要があり、増分を指定できるようにしたいと思います。たとえば、3つの証券があり、増分を1%にしたい場合、最初の行は98%、1%、1%になります。次の行は、97%、1%、2%などになります。最終的には、(指定された間隔に基づいて)可能なすべての割り当ての組み合わせを含む大きなテーブルができます。それは役に立ちますか?~~~~~~

Rで割り当てテーブルを作成しようとしていますが、壁にぶつかりました。私はこの問題を複数の本やウェブサイトで調査しましたが、簡単なアプローチを見つけることができないようです。

最も基本的な形式では、次のようなテーブルを生成しようとしています。

変数が3つだけで、各行の合計が1になると仮定します。

    v1   v2   v3 v1...v2...v3
1 0.25 0.25 0.50            1
2 0.25 0.50 0.25            1
3 0.50 0.25 0.25            1
4 0.75 0.25 0.00            1
5 0.75 0.00 0.25            1
6 1.00 0.00 0.00            1
7 0.50 0.25 0.25            1
8 0.25 0.25 0.50            1

理想的には、行列を返したいです。私はこれまでRを使ってこれを行うことができませんでした。誰かが私を助けることができますか?どこから始めればいいのかわからない。

どうもありがとうございます、

アンドリュー

4

3 に答える 3

2

コメントに基づいて回答を更新

あなたが探しているのは順列を生成する方法のようです。その場合はpermutations、「gtools」パッケージから試してください。まず、すべての順列を生成してから、行の合計が100になる順列のみを選択します。

> ## install.packages(gtools)
> library(gtools)
> x <- permutations(101, 3, 0:100, repeats.allowed=TRUE)
> y <- x[rowSums(x) == 100, ]
> head(y)
     [,1] [,2] [,3]
[1,]    0    0  100
[2,]    0    1   99
[3,]    0    2   98
[4,]    0    3   97
[5,]    0    4   96
[6,]    0    5   95
> tail(y)
        [,1] [,2] [,3]
[5146,]   98    0    2
[5147,]   98    1    1
[5148,]   98    2    0
[5149,]   99    0    1
[5150,]   99    1    0
[5151,]  100    0    0

元の回答

単純化しすぎていないことを願っていますが、このようなことを試すことができるかもしれません。負の数を含めるかどうかは指定しません。私はそうは思わなかった。

Rの乱数ジェネレーターの1つを使用する小さな関数を作成します。私はrunif自分の関数で使用しました。関数の引数には、必要な列の数(デフォルトを3に設定)、最小値、および最大値が含まれます。

myFun <- function(n = 3, min = 0, max = 1) {
  temp <- runif(n = n, min = min, max = max)
  temp/sum(temp)
}

必要な行replicate数を取得するために使用します。ここでは、5行を作成すると言いました。

set.seed(1)
y <- t(replicate(5, myFun()))
y
#           [,1]      [,2]      [,3]
# [1,] 0.2193406 0.3074170 0.4732425
# [2,] 0.4522318 0.1004252 0.4473430
# [3,] 0.4227516 0.2957136 0.2815348
# [4,] 0.1390588 0.4635751 0.3973661
# [5,] 0.3731857 0.2086423 0.4181721

各行が実際に1になることを確認します。

rowSums(y)
# [1] 1 1 1 1 1
于 2013-03-26T17:56:12.407 に答える
2

決定論的アプローチ:

n非負の変数で可能なすべての組み合わせが必要な場合は、合計を1にして、間隔[0,1]s等しい部分に分割します。次のコードを使用できます。

n最初に、合計が次の整数の順列を与える関数s

perms <- function(n, s)
{
    if(n==1) return(matrix(s,nrow=1,ncol=1))

    do.call(rbind, lapply(0:s, function(i) cbind(perms(n-1, s-i), i, deparse.level=0)))
}

次に、列の数と「カット」の数を定義し、再スケーリングします。

> perms(3,4)/4
      [,1] [,2] [,3]
 [1,] 1.00 0.00 0.00
 [2,] 0.75 0.25 0.00
 [3,] 0.50 0.50 0.00
 [4,] 0.25 0.75 0.00
 [5,] 0.00 1.00 0.00
 [6,] 0.75 0.00 0.25
 [7,] 0.50 0.25 0.25
 [8,] 0.25 0.50 0.25
 [9,] 0.00 0.75 0.25
[10,] 0.50 0.00 0.50
[11,] 0.25 0.25 0.50
[12,] 0.00 0.50 0.50
[13,] 0.25 0.00 0.75
[14,] 0.00 0.25 0.75
[15,] 0.00 0.00 1.00
于 2013-03-26T18:55:32.653 に答える
0

考えただけですが...

各列の値をどのように決定するかは完全には明確ではありません。サンプルから推測するseq(0, 1, .25)と、行の合計が1

set.seed(222)
vals <- seq(0, 1, .25)

TotalRows <- 12
TotalCols <- 3
Lim       <- 1

# First Column
myDF <- data.frame(sample(vals, TotalRows, TRUE))

# Each next column, except last
for (i in 2:(TotalCols-1))
    myDF[, i] <- apply(myDF, 1, function(x) sample(vals[vals + sum(x) <= Lim], 1))

# Last column is difference from Lim (ie, from 1)
myDF[, TotalCols] <- apply(myDF, 1, function(x) Lim - sum(x) )

# Set Colnames if needed
colnames(myDF) <- paste0("Col", 1:TotalCols)

# Total Column if needed
myDF[, "TOTAL"] <- apply(myDF, 1, sum)

myDF

 #     Col1 Col2 Col3 TOTAL
 #  1  1.00 0.00 0.00     1
 #  2  0.00 0.75 0.25     1
 #  3  0.50 0.50 0.00     1
 #  4  0.00 0.00 1.00     1
 #  5  1.00 0.00 0.00     1
 #  6  1.00 0.00 0.00     1
 #  7  0.25 0.00 0.75     1
 #  8  0.50 0.00 0.50     1
 #  9  0.50 0.50 0.00     1
 #  10 0.00 0.25 0.75     1
 #  11 0.50 0.00 0.50     1
 #  12 0.00 0.50 0.50     1



素晴らしい機能として:

# example call:
creatTable(TotalRows=12, TotalCols=8)

# definition:
creatTable <- function(TotalRows, TotalCols, Lim=1, vals=seq(0, 1, .25), columnPrfx="Col")  {
  myDF <- data.frame(sample(vals, TotalRows, TRUE))
  for (i in 2:(TotalCols-1))
      myDF[, i] <- apply(myDF, 1, function(x) sample(vals[vals + sum(x) <= Lim], 1))
  myDF[, TotalCols] <- apply(myDF, 1, function(x) Lim - sum(x) )
  colnames(myDF) <- paste0(columnPrfx, 1:TotalCols)
  myDF[, "TOTAL"] <- apply(myDF, 1, sum)
}
于 2013-03-26T17:36:37.993 に答える