2017-05-05 14 views
2

簡略化されたコード(これは私の状況と似ていますが、これは私の状況と似ています)を使ってこれを調べると、現在作業しているコードは長く、価値のない言葉私は喜んでこれに答えるために必要なものを追加します:ループの出力をリストからデータフレームへ変換するR

私は状況を持っているようなforループ:

[[1]] 
[1] "1,261" 

[[2]] 
[1] "2,103" 

[[1]] 
[1] "313" 

[[2]] 
[1] "1,165" 

[[1]] 
[1] "2,073" 

[[2]] 
[1] "2,206" 

[[1]] 
[1] "2,417" 

[[2]] 
[1] "2,258" 

私は希望:私のようなベクトルを返します

data2 <- data.frame("Chocolate" = c(0.25), "Strawberry" = c(.16), 
       "Vanilla" = c(0.64), "Blueberry" = c(.75)) 

for (i in 1:4) { 
    freqSim <- data.frame(sample(0:1, length(1:100), replace=T, prob = c(1-data2[i],data2[i]))) 

    lossCol <- freqSim*(runif(n=100, min=0, max=7000)) 

    costAvg <- mean(as.numeric(unlist(lossCol))) 
    costSD <- sd(as.numeric(unlist(lossCol))) 

    costAvg <- formatC(costAvg, format='d', big.mark=",") 
    costSD <- formatC(costSD, format='d', big.mark= ",") 

    stats <- list() 
    stats[[i]] <- list(costAvg,costSD) 

    print(stats[[i]]) 
} 

理想的には次のような行列のようなものです:

自分自身を崖から投げることなくこれを行う方法はありますか?

答えて

1

簡単な修正です:

data2 <- data.frame("Chocolate" = c(0.25), "Strawberry" = c(.16), 
     "Vanilla" = c(0.64), "Blueberry" = c(.75)) 

stats <- data.frame(row.names = c("Label A", "Label B")) 

for (i in 1:4) { 
    freqSim <- data.frame(sample(0:1, length(1:100), replace=T, 
      prob = c(1-data2[i],data2[i]))) 

    lossCol <- freqSim*(runif(n=100, min=0, max=7000)) 

    costAvg <- mean(as.numeric(unlist(lossCol))) 
    costSD <- sd(as.numeric(unlist(lossCol))) 

    costAvg <- formatC(costAvg, format='d', big.mark=",") 
    costSD <- formatC(costSD, format='d', big.mark= ",") 

    stats["Label A", i] <- costAvg 
    stats["Label B", i] <- costSD 
} 

colnames(stats) <- colnames(data2) 

結果:

 Chocolate Strawberry Vanilla Blueberry 
Label A  764  470 2,003  2,932 
Label B  1,674  1,418 2,202  2,315 

は、私が操作のこれらの種類のtidyrを使用して代わりのベースRでそれをやってを見てことをお勧めします、 できれば。

1

我々はsimplify2array

res <- simplify2array(stats) 
dimnames(res) <- list(paste("Label", c("A", "B")), names(data2)) 

NOTEを使用してこれを行うことができます。length前を持って、より良いオプションが割り当てることですforループ

stats <- list() 

を定義することを確認します割り当てられたieすなわち

stats <- vector("list", length(data2)) 
1

あなたが出力テーブルとして与えたものを正確に取得するには、これを試してください。正しい命名規則を適用する時間がありませんでした。申し訳ありません。ここで

data2 <- data.frame("Chocolate" = c(0.25), "Strawberry" = c(.16), 
        "Vanilla" = c(0.64), "Blueberry" = c(.75)) 
x = c("Chocolate", "Strawberry", "Vanilla", "Blueberry") 
y = c("Label A", "Label B") 

data3 = matrix(nrow = 2, ncol = 4) 
colnames(data3) = x 
row.names(data3) = y 

for (i in 1:4) { 
    freqSim <- data.frame(sample(0:1, length(1:100), replace = T, prob = c(1-data2[i],data2[i]))) 

    lossCol <- freqSim*(runif(n=100, min=0, max=7000)) 

    costAvg <- mean(as.numeric(unlist(lossCol))) 
    costSD <- sd(as.numeric(unlist(lossCol))) 

    costAvg <- formatC(costAvg, format='d', big.mark=",") 
    costSD <- formatC(costSD, format='d', big.mark= ",") 

    data3[1, i] = costAvg 
    data3[2, i] = costSD 
} 
1

dplyrの例を示します。それはあなたが望んでいた行列を与えることはありませんが、それはforループを回避するために滑らかな印象の方法だ:

freqSim <- lapply(names(data2), function(x) 
        sample(0:1, length(1:100), replace=T, 
        prob=c(1-data2[x], data2[x]))) 
names(freqSim) <- names(data2) 

lossCol <- lapply(freqSim, function(x) x*(runif(n=100, min=0, max=7000))) 

do.call(data.frame, lossCol) %>% 
    gather(type, val) %>% 
    group_by(type) %>% 
    summarise(mean=mean(val), sd=sd(val)) %>% 
    mutate_at(.cols=vars(mean, sd), .funs = funs(format(., format="d", big.mark=","))) 

# A tibble: 4 × 3 
     type  mean  sd 
     <chr>  <chr>  <chr> 
1 Blueberry 2,911.8587 2,481.310 
2 Chocolate 810.6141 1,820.357 
3 Strawberry 680.2027 1,659.491 
4 Vanilla 2,302.0011 2,305.148 
1

あなたが本当に行列形式の出力をしたい場合は、あなたがouterを使用してベースRでこれを行うことができます。例えば、mtcarsの各列の平均値と中央値を計算するために、あなたができる:

> outer(list(mean=mean, median=median), as.data.frame(mtcars), Vectorize(function(f,y) f(y))) 
      mpg cyl  disp  hp  drat  wt  qsec  vs  am gear carb 
mean 20.090625 6.1875 230.721875 146.6875 3.5965625 3.21725 17.84875 0.4375 0.40625 3.6875 2.8125 
median 19.200000 6.0000 196.300000 123.0000 3.6950000 3.32500 17.71000 0.0000 0.00000 4.0000 2.0000 

外の最初の引数は適用したい機能の名前のリストである、第二の反復処理する列であります最後の引数は、列の関数を評価する関数です。ここにVectorizeが必要です。

はサンプルを生成します:

次のようになり
>  freqSim <- lapply(data2, function(x) sample(0:1, length(1:100), replace=T, prob=c(1-x,x)) *(runif(n=100, min=0, max=7000))) 

> str(freqSim) 
List of 4 
$ Chocolate : num [1:100] 0 0 0 0 0 ... 
$ Strawberry: num [1:100] 0 0 0 0 0 0 0 0 0 0 ... 
$ Vanilla : num [1:100] 4175 1456 0 1201 852 ... 
$ Blueberry : num [1:100] 0 3896 3794 5096 2901 ... 

は、あなたの関数を宣言します。

あなたのケースでは

、私は三つの部分にあなたのコードを分割う

> funs <- list(`Label A`=function(x) formatC(mean(x), format='d', big.mark=","), 
       `Label B`=function(x) formatC(sd(x), format='d', big.mark=",")) 

使用outer

> outer(funs, freqSim, Vectorize(function(f,y) f(y))) 
     Chocolate Strawberry Vanilla Blueberry 
Label A "518"  "427"  "2,044" "2,441" 
Label B "1,417" "1,290" "2,250" "2,259" 
関連する問題