繁体   English   中英

如何根据列中的级别对重复值求和并输出计数表?

[英]How do I sum recurring values according to a level in a column and output a table of counts?

我是R的新手,我的数据看起来像这样:

categories <- c("A","B","C","A","A","B","C","A","B","C","A","B","B","C","C")
animals <- c("cat","cat","cat","dog","mouse","mouse","rabbit","rat","shark","shark","tiger","tiger","whale","whale","worm")
dat <- cbind(categories,animals)

有些动物根据类别重复。 例如,“cat”出现在所有三个类别A,B和C.

我喜欢我的新数据帧输出看起来像这样:

A   B   C   count
1   1   1   1
1   1   0   2
1   0   1   0
0   1   1   2
1   0   0   2
0   1   0   0
0   0   1   2
0   0   0   0

A,B和C下的数字1表示动物出现在该类别中,0表示动物未出现在该类别中。 例如,第一行在所有三个类别中都有1。 第一行的计数为1,因为“cat”是每个类别中唯一重复的动物。

R中有一个函数可以帮助我实现这个目标吗? 先感谢您。

我们可以使用table来创建categoriesanimals的交叉列表,转置,转换为data.frame, group_by所有categories并计算每个组合的频率:

library(dplyr)
library(tidyr)

as.data.frame.matrix(t(table(dat))) %>%
  group_by_all() %>%
  summarize(Count = n())

结果:

# A tibble: 5 x 4
# Groups:   A, B [?]
      A     B     C Count
  <int> <int> <int> <int>
1     0     0     1     2
2     0     1     1     2
3     1     0     0     2
4     1     1     0     2
5     1     1     1     1

编辑 (感谢@C.Braun)。 以下是如何包含零A,B,C组合:

as.data.frame.matrix(t(table(dat))) %>%
  bind_rows(expand.grid(A = c(0,1), B = c(0,1), C = c(0,1))) %>%
  group_by_all() %>%
  summarize(Count = n()-1) 

或者complete按照@Ryan的建议:

as.data.frame.matrix(t(table(dat))) %>%
  mutate(non_missing = 1) %>%
  complete(A, B, C) %>%
  group_by(A, B, C) %>%
  summarize(Count = sum(ifelse(is.na(non_missing), 0, 1))) 

结果:

# A tibble: 8 x 4
# Groups:   A, B [?]
      A     B     C Count
  <dbl> <dbl> <dbl> <dbl>
1     0     0     0     0
2     0     0     1     2
3     0     1     0     0
4     0     1     1     2
5     1     0     0     2
6     1     0     1     0
7     1     1     0     2
8     1     1     1     1

我们有

xxtabs <- function(df, formula) {
    xt <- xtabs(formula, df)
    xxt <- xtabs( ~ . , as.data.frame.matrix(xt))
    as.data.frame(xxt)
}

> xxtabs(dat, ~ animals + categories)
  A B C Freq
1 0 0 0    0
2 1 0 0    2
3 0 1 0    0
4 1 1 0    2
5 0 0 1    2
6 1 0 1    0
7 0 1 1    2
8 1 1 1    1

dat应该真正构造为data.frame(animals, categories) )。 这种基本方法使用xtabs()来形成第一个交叉表

xt <- xtabs(~ animals + categories, dat)

然后使用as.data.frame.matrix()强制转换为第二个data.frame,并使用计算data.frame的所有列的第二个交叉制表。

xxt <- xtabs(~ ., as.data.frame.matrix(xt))

被迫达到理想的形式

as.data.frame(xxt)

我最初说这种方法是'奥术',因为它依赖于as.data.frame()as.data.frame.matrix()之间差异的知识; 我认为xtabs()是基础R的用户应该知道的工具。 我看到其他解决方案也需要这些神秘的知识,以及更多模糊(例如, complete()group_by_all() ,funs funs() )tidyverse部分的知识。 此外,其他答案不是(或至少不是以允许的方式编写)容易推广; xxtabs()实际上并不知道有关传入data.frame结构的任何信息,而传入数据的隐含知识存在于其他答案中。

从整洁的方法中学到的一个“经验教训”是首先放置数据参数,允许管道

dat %>% xxtabs(~ animals + categories)

如果我理解正确,这应该可以解决问题。

require(tidyverse)

 dat %>% 
  mutate(value = 1) %>%
  spread(categories, value) %>%
  mutate_if(is.numeric, funs(replace(., is.na(.), 0))) %>% 
  mutate(count = rowSums(data.frame(A, B, C), na.rm = TRUE)) %>%
  group_by(A, B, C) %>%
  summarize(Count = n()) 

# A tibble: 5 x 4
# Groups:   A, B [?]
      A     B     C Count
  <dbl> <dbl> <dbl> <int>
1    0.    0.    1.     2
2    0.    1.    1.     2
3    1.    0.    0.     2
4    1.    1.    0.     2
5    1.    1.    1.     1

添加data.table解决方案。 首先,使用dat将动物与类别联系起来。 然后,使用CJ创建A,B,C的组合。 将这些组合与dat连接起来,并计算每个组合的出现次数。

dcast(as.data.table(dat), animals ~ categories, length)[
    CJ(A=0:1, B=0:1, C=0:1), .(count=.N), on=c("A","B","C"), by=.EACHI]

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM