2011-03-17 80 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))