频率计数,按R中的两列分组

时间:2013-02-06 21:27:36

标签: r

如何计算两列中出现的频率? 样本数据:

> sample <- dput(df)
structure(list(Nom_xp = c("A1FAA", "A1FAJ", "A1FBB", "A1FJA", 
"A1FJR", "A1FRJ"), GB05.x = c(100L, 98L, NA, 100L, 102L, 98L), 
    GB05.1.x = c(100L, 106L, NA, 100L, 102L, 98L), GB18.x = c(175L, 
    173L, 177L, 177L, 173L, 177L), GB18.1.x = c(177L, 175L, 177L, 
    177L, 177L, 177L)), .Names = c("Nom_xp", "GB05.x", "GB05.1.x", 
"GB18.x", "GB18.1.x"), row.names = c(NA, 6L), class = "data.frame")

计算频率:

apply(sample[,2:5],2,table)

现在,如何通过列的前缀或每两列组合计数?四个第一列的预期输出将是一个列表:

$GB05
98 100 102 106
3  4   2   1
$GB18
173 175 177
2   2   8

获得前两列计数的一种方法:

  table(c(apply(sample[,2:3],2,rbind)))
98 100 102 106 
  3   4   2   1

但是如何将它应用于整个data.frame?

3 个答案:

答案 0 :(得分:2)

如果您想将table应用于整个数据框,可以使用:

table(unlist(sample[,-1]))

给出了:

 98 100 102 106 173 175 177 
  3   4   2   1   2   2   8 

如果您想按列名前缀分组,例如第4个第一个字符,您可以执行以下操作:

cols <- names(sample)[-1]
groups <- unique(substr(cols,0,4))
sapply(groups, function(name) table(unlist(sample[,grepl(paste0("^",name),names(sample))])))

给出了:

$GB05

 98 100 102 106 
  3   4   2   1 

$GB18

173 175 177 
  2   2   8 

答案 1 :(得分:1)

我会说朱巴的答案是正确的,但鉴于你正在寻找别的东西,也许就是这个?

library(reshape2)

x <- melt( sample[ , 2:5 ] )

table( x[ , c( 'variable' , 'value' ) ] ) 

给出了

          value
variable   98 100 102 106 173 175 177
  GB05.x    2   2   1   0   0   0   0
  GB05.1.x  1   2   1   1   0   0   0
  GB18.x    0   0   0   0   2   1   3
  GB18.1.x  0   0   0   0   0   1   5

请提供您所需输出结构的示例:)

答案 2 :(得分:1)

这是另一个答案,这是安东尼的答案和朱巴的答案之间的混合。

第一步是将data.frame转换为“长”data.frame。我通常会尽可能使用stack,但您也可以library(reshape2); df2 <- melt(df)获取类似于df2对象的输出。

df2 <- data.frame(df[1], stack(df[-1]))
head(df2)
#   Nom_xp values    ind
# 1  A1FAA    100 GB05.x
# 2  A1FAJ     98 GB05.x
# 3  A1FBB     NA GB05.x
# 4  A1FJA    100 GB05.x
# 5  A1FJR    102 GB05.x
# 6  A1FRJ     98 GB05.x

接下来,我们需要知道ind的唯一值。朱巴用substr做到了这一点,但我在这里用gsub和正则表达式完成了。我们无需将其添加到data.frame;我们可以直接在其他函数中调用它。立即想到的两个函数是bytapply,它们都为您提供了所需的输出。

by(df2$values, 
   list(ind = gsub("([A-Z0-9]+)\\..*", "\\1", df2$ind)), 
   FUN=table)
# ind: GB05
# 
#  98 100 102 106 
#   3   4   2   1 
# ------------------------------------------------------------------------------ 
# ind: GB18
# 
# 173 175 177 
#   2   2   8 

tapply(df2$values, gsub("([A-Z0-9]+)\\..*", "\\1", df2$ind), FUN = table)
# $GB05
# 
#  98 100 102 106 
#   3   4   2   1 
# 
# $GB18
# 
# 173 175 177 
#   2   2   8