根据R中每列中的每个值创建计数表

Sar*_*rah 3 r count dplyr

我有一个这样开始的数据表:

    test <- data.frame("AZ" = c("ABCD, AAAA, BBBB"), "AK" = c("ABCD"), "NJ" = c("BBBC", "AAAA"))
Run Code Online (Sandbox Code Playgroud)

每列都是一个州(亚利桑那州、阿拉斯加、新泽西州),这些列中的值是代码。如果单个单元格中有多个代码,则将以逗号分隔。

我想创建一个计数表,显示每个州显示的每个代码的数量。所以表格最终看起来像这样:

    test2 <- data.frame("ABCD" = c("2", "2", "0"), "AAAA" = c("2", "0", "1"), "BBBB" = c("2", "0", "0"), "BBBC" = c("0", "0", "1"), row.names = c("AZ", "AK", "NJ"))
Run Code Online (Sandbox Code Playgroud)

有没有办法在 R 中输出这样的表?我一直在玩 dplyr,但到目前为止还没有运气。感谢您的帮助 :)

akr*_*run 5

我们可以gather将“长”格式转换为“长”格式,然后用 分隔符将“值”分割,,separate_rows, 获取频率count,转换spread为“宽”格式

library(tidyverse)
gather(test) %>% 
   separate_rows(value) %>% 
   count(key, value) %>%
   spread(value, n, fill = 0) %>%
   column_to_rownames('key')
#   AAAA ABCD BBBB BBBC
#AK    0    2    0    0
#AZ    2    2    2    0
#NJ    1    0    0    1
Run Code Online (Sandbox Code Playgroud)

注意:如果我们需要“长”格式的输出,则无需spread

gather(test) %>% 
    separate_rows(value) %>% 
    count(key, value)
# A tibble: 6 x 3
#  key   value     n
#  <chr> <chr> <int>
#1 AK    ABCD      2
#2 AZ    AAAA      2
#3 AZ    ABCD      2
#4 AZ    BBBB      2
#5 NJ    AAAA      1
#6 NJ    BBBC      1
Run Code Online (Sandbox Code Playgroud)

更新

如果我们还需要按“行”分组,请创建一row_number()列,然后将gather, 转换为“长”格式并countunited“key”和“rn”列上

test %>%
   mutate(rn = row_number()) %>% 
   gather(key, val, -rn) %>%
   separate_rows(val) %>% 
   unite(key, key, rn) %>% 
   count(key, val) %>% 
   spread(val, n, fill = 0) %>%
   column_to_rownames('key')
#      AAAA ABCD BBBB BBBC
#AK_1    0    1    0    0
#AK_2    0    1    0    0
#AZ_1    1    1    1    0
#AZ_2    1    1    1    0
#NJ_1    0    0    0    1
#NJ_2    1    0    0    0
Run Code Online (Sandbox Code Playgroud)

或者使用base R

table(stack(lapply(test, function(x) unlist(strsplit(as.character(x), ", "))))[2:1])
Run Code Online (Sandbox Code Playgroud)