3

我在 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 等等。但我现在真的卡住了,我不知道如何前进......</ p>

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

4

5 回答 5

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

因此,要获得“a”列和“1”组中“3”的数量,您可以这样做

> dftab[3,'a',1]
[1] 4
于 2011-03-17T12:16:25.303 回答
2

tapply和的组合apply可以创建您想要的数据:

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

但是,当一个分组中没有所有元素时,如在 中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
于 2011-03-17T12:44:07.367 回答
0

我相信有人会有比这更优雅的解决方案,但你可以用一个简单的函数和包来拼凑dlplyplyr

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,column = a,根据您上面的示例。

于 2011-03-17T10:51:55.863 回答
0

你没有说你喜欢这些数据。该by函数可能会为您提供您喜欢的输出。

by(df, df$id, function(x) lapply(x[,-1], table))
于 2014-05-26T14:52:01.517 回答
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
于 2014-03-31T21:46:09.960 回答