计算data.frame子集中数字的出现次数

时间:2011-03-17 09:13:44

标签: r subset

我在R中有一个数据帧,类似于以下内容。实际上我真正的'df'数据帧比这里的数据框要大得多,但我真的不想让任何人感到困惑,所以这就是为什么我尽量简化事情。

所以这是数据框。

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'和id号'1'(后者见列'id'),代码将是这样的:

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

##The results are:
[1] 3 7

只是简单地解释一下我的结果:在'a'栏中(并且只关注那些'id'栏中编号为'1'的记录)我们可以说数字'1'出现3次而数字'3'出现7次。

再次,只是为了向您展示另一个例子。对于列'a'和id号为'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'数据帧,因此行和列的总数可能会随着时间的推移而改变......

到目前为止我所做的是我将'df'数据框分隔为列,如下所示:

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

所以df.2将引用df $ a,df.3将等于df $ b,df.4将等于df $ c等。但我现在真的被困住了,我不知道如何前进...

是否有正确的“自动”方法来解决这个问题?

5 个答案:

答案 0 :(得分: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

答案 1 :(得分:2)

tapplyapply的组合可以创建您想要的数据:

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

但是,当分组中没有所有元素时,如1a中所示,结果将是该id组的列表,而不是一个漂亮的表(矩阵)。< / p>

$`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

答案 2 :(得分:0)

我确信有人会有比这更优雅的解决方案,但您可以使用dlply包中的简单函数和plyr来拼凑它。

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变量;第二个是{id}变量每列的table结果。例如:

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

1 2 3 
4 3 3 

对于id变量= 2,列= a,按照上面的示例。

答案 3 :(得分: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

答案 4 :(得分:0)

您没有说出您对数据的喜好。 by函数可能会为您提供您喜欢的输出。

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