2011-03-17 57 views
3

我在R中有一個數據框,與以下內容類似。實際上,我的真正'DF'數據框比這個更大,但我真的不想混淆任何人,所以我儘可能地儘量簡化。計算data.frame中的數字出現次數。框架

所以這裏是數據框架。

id <-c(1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,3,3,3,3,3,3,3,3,3,3) 
a <-c(3,1,3,3,1,3,3,3,3,1,3,2,1,2,1,3,3,2,1,1,1,3,1,3,3,3,2,1,1,3) 
b <-c(3,2,1,1,1,1,1,1,1,1,1,2,1,3,2,1,1,1,2,1,3,1,2,2,1,3,3,2,3,2) 
c <-c(1,3,2,3,2,1,2,3,3,2,2,3,1,2,3,3,3,1,1,2,3,3,1,2,2,3,2,2,3,2) 
d <-c(3,3,3,1,3,2,2,1,2,3,2,2,2,1,3,1,2,2,3,2,3,2,3,2,1,1,1,1,1,2) 
e <-c(2,3,1,2,1,2,3,3,1,1,2,1,1,3,3,2,1,1,3,3,2,2,3,3,3,2,3,2,1,3) 

df <-data.frame(id,a,b,c,d,e) 
df 

基本上我想要做的就是拿到號碼的出現爲每列(A,B,C,d,e)和每個ID組(1,2,3)(此後者分組見我的專欄'id')。

所以,對於列「A」和身份證號碼「1」(後者見列「ID」)代碼將是這樣的:

as.numeric(table(df[1:10,2])) 

##The results are: 
[1] 3 7 

只是簡單介紹一下我的結果:在'a'列中(並且僅關於在'id'列中具有數字'1'的那些記錄),我們可以說數字「1」發生3次並且數字「3」發生7次。

再次,只是爲了向您展示另一個例子。對於列「A」和身份證號碼「2」(後者分組再次看到列「ID」):

as.numeric(table(df[11:20,2])) 

##After running the codes the results are: 
[1] 4 3 3 

讓我再解釋一下:在列「A」和關於只有那些觀察其在'id'列中具有數字'2'),我們可以說數字'1'發生4次,數字'2'發生3次,數字'3'發生3次。

所以這就是我想要做的。計算每個自定義子集的數字出現次數(然後將這些值收集到數據幀中)。我知道這不是一個困難的任務,但問題是,我將不得不定期更改輸入「DF」數據幀,因此行和列的總數可能會隨着時間而改變...

什麼我已經做了到目前爲止,我已經按列分隔「東風」數據幀,這樣的:

for (z in (2:ncol(df))) assign(paste("df",z,sep="."),df[,z]) 

所以df.2將引用的df,一個$,df.3將等於DF $ b,DF。 4將等於DF $ c等,但我現在真的卡住了,我不知道如何前進......

有沒有一個適當的,「自動」的方式來解決這個問題?

回答

0

我確定有人會有比這更優雅的解決方案,但你可以用一個簡單的功能將它拼湊在一起,並從plyr包中打包dlply

ColTables <- function(df) { 
    counts <- list() 
    for(a in names(df)[names(df) != "id"]) { 
    counts[[a]] <- table(df[a]) 
    } 
    return(counts) 
} 

results <- dlply(df, "id", ColTables) 

這讓你回到列表 - 列表的第一個「層」將是id變量;第二個table針對該id變量的每個列的結果。例如:

> results[['2']]['a'] 
$a 

1 2 3 
4 3 3 

對於id變量= 2,列= a,根據您的上述示例。

5

怎麼樣 -

> library(reshape) 

> dftab <- table(melt(df,'id')) 
> dftab 
, , value = 1 

    variable 
id a b c d e 
    1 3 8 2 2 4 
    2 4 6 3 2 4 
    3 4 2 1 5 1 

, , value = 2 

    variable 
id a b c d e 
    1 0 1 4 3 3 
    2 3 3 3 6 2 
    3 1 4 5 3 4 

, , value = 3 

    variable 
id a b c d e 
    1 7 1 4 5 3 
    2 3 1 4 2 4 
    3 5 4 4 2 5 

因此,要獲得「第3欄中的 'A' 和組 '的1號' 你可能只是做

> dftab[3,'a',1] 
[1] 4 
+0

+1非常乾淨.. – 2011-03-17 18:31:56

2

tapplyapply組合可以創建你想要的數據:

tapply(df$id,df$id,function(x) apply(df[id==x,-1],2,table)) 

howe ver,當一個分組沒有包含所有元素時,如1a,結果將是該組id的列表,而不是一個很好的表格(矩陣)。

$`1` 
$`1`$a 

1 3 
3 7 

$`1`$b 

1 2 3 
8 1 1 

$`1`$c 

1 2 3 
2 4 4 

$`1`$d 

1 2 3 
2 3 5 

$`1`$e 

1 2 3 
4 3 3 


$`2` 
    a b c d e 
1 4 6 3 2 4 
2 3 3 3 6 2 
3 3 1 4 2 4 

$`3` 
    a b c d e 
1 4 2 1 5 1 
2 1 4 5 3 4 
3 5 4 4 2 5 
+0

可以使用的一個因素,確保零個計數來通過: 'lapply(分割(DF [-1],DF $ ID),應用2,功能( x)表(factor(x,1:3)))'' – Charles 2011-03-17 15:46:43

0

它使用的是aggregate功能,但你必須將列添加到您的數據幀

> df$freq <- 0 
> aggregate(freq~a+id,df,length) 
    a id freq 
1 1 1 3 
2 3 1 7 
3 1 2 4 
4 2 2 3 
5 3 2 3 
6 1 3 4 
7 2 3 1 
8 3 3 5 

當然,你可以編寫一個函數來做到這一點,所以它更容易做的一種方式頻繁地執行操作,而且您不必在實際數據框中添加列

> frequency <- function(df,groups) { 
+ relevant <- df[,groups] 
+ relevant$freq <- 0 
+ aggregate(freq~.,relevant,length) 
+ } 
> frequency(df,c("b","id")) 
    b id freq 
1 1 1 8 
2 2 1 1 
3 3 1 1 
4 1 2 6 
5 2 2 3 
6 3 2 1 
7 1 3 2 
8 2 3 4 
9 3 3 4 
0

您沒有說明您希望如何使用數據。 by函數可能會給你你喜歡的輸出。

by(df, df$id, function(x) lapply(x[,-1], table))