5

大きなデータ フレームを取得し、値の各列をそれらの値の累積頻度 (昇順で並べ替え) で置き換えるプログラムを作成しようとしています。たとえば、値の列が 5、8、3、5、4、3、8、5、5、1 の場合、相対度数と累積度数は次のようになります。

  • 1: rel_freq=0.1、cum_freq = 0.1
  • 3: rel_freq=0.2、cum_freq = 0.3
  • 4: rel_freq=0.1、cum_freq = 0.4
  • 5: rel_freq=0.4、cum_freq = 0.8
  • 8: rel_freq=0.2、cum_freq = 1.0

元の列は次のようになります: 0.8、1.0、0.3、0.8、0.4、0.3、1.0、0.8、0.8、0.1

次のコードはこの操作を正しく実行しますが、おそらくネストされたループが原因でスケーリングが不十分です。このタスクをより効率的に実行する方法はありますか?

mydata = read.table(.....)

totalcols = ncol(mydata)
totalrows = nrow(mydata)

for (i in 1:totalcols) {
    freqtable = data.frame(table(mydata[,i])/totalrows)  # create freq table
    freqtable$CumSum = cumsum(freqtable$Freq)   # calc cumulative freq

    hashtable = new.env(hash=TRUE)
    nrows = nrow(freqtable)

    # store cum freq in hash
    for (x in 1:nrows) {
        dummy = toString(freqtable$Var1[x])
        hashtable[[dummy]] = freqtable$CumSum[x]
    }

    # replace original data with cum freq
    for (j in 1:totalrows) {
        dummy = toString(mydata[j,i])
        mydata[j,i] = hashtable[[dummy]]
    }
}
4

2 に答える 2

2

forこれは、ループなしで単一の列を処理します。

R> x <- c(5, 8, 3, 5, 4, 3, 8, 5, 5, 1)
R> y <- cumsum(table(x)/length(x))
R> y[as.character(x)]
  5   8   3   5   4   3   8   5   5   1 
0.8 1.0 0.3 0.8 0.4 0.3 1.0 0.8 0.8 0.1 
于 2012-10-23T19:02:07.907 に答える
1

これが1つの方法です。それぞれがサンプル データを含む 2 つの変数を持つデータ フレームの使用

d <- data.frame(var1 = c(5, 8, 3, 5, 4, 3, 8, 5, 5, 1),
                var2 = c(5, 8, 3, 5, 4, 3, 8, 5, 5, 1))

簡単な関数を使用して

  1. cumsum()で与えられる相対比率の を生成しtable(x) / length(x)、次に
  2. match()累積和の表の名前を持つ変数の観測値、次に
  3. IDの一致を使用して、累積合計の表から選択します(そして名前を付けません)

そのような関数は次のとおりです。

f <- function(x) {
    tab <- cumsum(table(x) / length(x))
    ind <- match(x, as.numeric(names(tab)))
    unname(tab[ind])
}

実際にはlapply()、データ フレームを使用して強制します。

out <- data.frame(lapply(d, f))
out

与える:

R> out
   var1 var2
1   0.8  0.8
2   1.0  1.0
3   0.3  0.3
4   0.8  0.8
5   0.4  0.4
6   0.3  0.3
7   1.0  1.0
8   0.8  0.8
9   0.8  0.8
10  0.1  0.1
于 2012-10-23T19:03:04.970 に答える