2013-07-09 33 views
1

我有一個data.frame有3列,其中每個可以被認爲是一個因素。我想計算data.frame上的一些統計數據並將其存儲在新框架中。更具體地講,我有以下字段:基於R data.frame上的多列的向量化元數據計算框架

obs, len, src 
A 10 X 
B 10 Y 

我想計算每個源擊穿每個長度(即從什麼源X是長度爲10的意見的比例是「A」 ,「B」等)

一個明顯的方法是使用兩個for循環遍歷長度和源,然後使用nrow()和count()來獲取我需要計算的值,像這樣:

relevant_subset <- data[data$src==source & data$len==length,] 
breakdown_info <- count(relevant_subset) 
breakdown_info$frac <- breakdown_info$freq/nrow(relevant_subset) 

有沒有辦法避免使用double for循環和使用更多v ectorized方法?是否有一種聰明的方式來預先分配可以爲每個長度和來源保存修改後的breakdown_info的新框架?

+0

你試過'table'? – asb

回答

1

這是什麼plyr包被造的!

格式爲<input_type><output_type>ply。例如,如果輸入是data.frame,並且您希望輸出爲data.frame,則使用ddply

要使用它,請指定輸入data.frame,要分組的列,然後是從每個組構造data.frame的函數。附加分組列的結果data.frames一起組裝到輸出data.frame中。

以類似於你的榜樣的東西,你可以做

require(plyr) 
a <- data.frame(
    obs=factor(c('A','A','A','B','B')), 
    len=c(10,10,10,10,210), 
    src=factor(c('X','X','Y','Y','Z'))) 

然後

z <- ddply(
    a, 
    .(obs), 
    function(df){ 
    data.frame(mean.len=mean(df$len)) 
    }) 

會產生

data.frame(
    obs=c('A', 'B'), 
    mean.length(10, 110)) 

ddply(a, .(src), function(df){ 
    data.frame(
    num.obs.A = sum(df$obs == 'A'), 
    num.obs.B = sum(df$obs == 'B'))}) 

會產生

data.frame(
    src=c('X','Y', 'Z'), 
    num.obs.A = c(3,1,0), 
    num.obs.B = c(0,1,1)) 

該網站是http://plyr.had.co.nz/具有良好的文檔了。

+0

謝謝,@momeara,這爲我工作!我的代碼的最終形式如下所示: 'ddply(data,。(length,source),function(df){' 'codes < - levels(df $ DSSP)' 'total < - length(df (代碼in)代碼中的代碼(代碼中的代碼)代碼[1],代碼['],代碼['1],代碼['1],代碼['1],代碼['1]代碼){' 'numRes < - sum(df $ DSSP == code)' 'foo [paste(「num。」,code,sep =「」)] < - numRes' 'foo [paste(「frac 。「,code,sep =」「)] < - numRes/total' '}' 'return(foo)' '})' – weitzner

+0

對不起, – weitzner

2

aggregate是你的這些任務的朋友:

示例數據:

set.seed(23) 
test <- data.frame(
    obs=sample(LETTERS[1:2],20,replace=TRUE), 
    len=sample(c(10,20),20,replace=TRUE), 
    src=sample(LETTERS[24:25],20,replace=TRUE) 
) 

總IT:

aggregate(obs ~ src + len,data=test, function(x) prop.table(table(x))) 

    src len  obs.A  obs.B 
1 X 10 0.6000000 0.4000000 
2 Y 10 0.2000000 0.8000000 
3 X 20 0.2500000 0.7500000 
4 Y 20 0.1666667 0.8333333 
+0

如果你不知道你在做什麼,或者沒有看到你的'aggregate'輸出的'str',''aggregate''可能會成爲你的敵人。對於這樣的情況,我認爲'do.call(data.frame,aggregate(obs〜src + len,data = test,function(x)prop.table(table(x))))'的輸出是更多的人會感到舒服。 – A5C1D2H2I1M1N2O1R2T1

0

你還沒有說明你爲什麼要在這裏輸出data.frame的原因。也許這對你最好,也許不是。您也不清楚比例是多少,但我認爲以下幾點可以最好地解決您的問題。

prop.table(table(test)) 

您可以稍微不同地輸入它,並按列的順序播放,以便您比較最容易檢查的內容。但是,這個輸出是一個三維數組,與data.frame有很大不同。

(交替使用的例子)

prop.table(with(test, table(src, obs, len)))