我在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等。但我现在真的被困住了,我不知道如何前进...
是否有正确的“自动”方法来解决这个问题?
答案 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)
tapply
和apply
的组合可以创建您想要的数据:
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))