【问题标题】:How do I summarize data that is broken into many columns?如何汇总分成多列的数据?
【发布时间】:2020-08-08 03:02:14
【问题描述】:

我有一个数据集,其中包含“选择尽可能多的应用”问题的答案,每个可能的答案都在单独的列中。所以,假设我们的问题是“你可以接受什么颜色的衬衫?”它看起来像这样:

id    Q3_Red Q3_Blue Q3_Green    Q3_Purple
9                    
8                    Green       Purple
7                    Green     
6     Red               
5                                Purple
4            Blue          
3            Blue                Purple
2     Red    Blue    Green     
1     Red                        Purple
10    Red                        Purple

您可以使用以下方法将其制成实际的数据框:

tmp <- data.frame("id" = c(009,008,007,006,005,004,003,002,001,010), "Q3_Red" = c("","","","Red","","","","Red","Red","Red"), "Q3_Blue" = c("","","","","","Blue","Blue","Blue","",""),
  "Q3_Green" = c("","Green","Green","","","","","Green","",""),
  "Q3_Purple" = c("","Purple","","","Purple","","Purple","","Purple","Purple")
)

我想用每个答案的计数来总结它,例如。

Red     4
Blue    3
Green   3
Purple  5

我可以用tmp %&gt;% count(Q3_Red) 之类的东西来计算每个人的数量,并将它们组织到自己的数据框中,但似乎必须有一种方法可以一举使用重塑功能来做到这一点。我看过gather()spread(),但我不知道如何将tidyrcount() 结合起来。

【问题讨论】:

  • 快速而肮脏的方式是colSums(tmp[,-1] != ""),但显然更正式的tidyverse方式是有人回答的
  • @BenToh 谢谢。我绝对想用这个项目来掌握 Tidyverse。

标签: r tidyr


【解决方案1】:

dplyrtidyr 是你的朋友:

library(dplyr)
library(tidyr)
tmp %>% 
  pivot_longer(cols = -id, values_to = "response") %>%   # pivot all columns but id
  filter(response != "") %>%        # remove blanks
  group_by(response) %>%            # group by response
  summarize(count = n())            # summarize and count
# A tibble: 4 x 2
  value  count
  <chr>  <int>
1 Blue       3
2 Green      3
3 Purple     5
4 Red        4

【讨论】:

  • pivot_longer()tidyr 包中的新gather()
  • @BenToh 感谢您提醒我pivot_longer() 来自tidyr。我更新了我的答案以包含对这两个包的引用。
  • 作为补充,group_by(response) %&gt;% summarize(count = n())可以简化为count(response, name = "count"),不需要使用group_by()
  • @DarrenTsai 谢谢。我实际上是想弄清楚是否有理由使用 group_by()summarize(count = n()) 而不仅仅是 count()
【解决方案2】:

您可以在dplyr 中使用na_if()"" 转换为NA,然后在tidyr 中使用pivot_longer() 以堆叠所有以Q3 开头的列。

注意: 使用na_if()是为了让pivot_longer()中的values_drop_na = T工作。

library(dplyr)
library(tidyr)

tmp %>% 
  mutate(across(-id, na_if, "")) %>% 
  pivot_longer(-id, values_drop_na = T) %>%
  count(value)

# # A tibble: 4 x 2
#   value      n
#   <chr>  <int>
# 1 Blue       3
# 2 Green      3
# 3 Purple     5
# 4 Red        4

或使用colSums()tibble::enframe()

tibble::enframe(colSums(tmp[-1] != ""))

# # A tibble: 4 x 2
#   name      value
#   <chr>     <dbl>
# 1 Q3_Red        4
# 2 Q3_Blue       3
# 3 Q3_Green      3
# 4 Q3_Purple     5

【讨论】:

    【解决方案3】:

    在基础 R 中我们可以使用

    summary(tmp[-1])
    # Q3_Red  Q3_Blue   Q3_Green  Q3_Purple
    #     :6       :7        :7         :5  
    #  Red:4   Blue:3   Green:3   Purple:5  
    

    【讨论】:

      【解决方案4】:

      你可以试试这个方法

      计算每个颜色列的频率

      tmp2 <- colSums(tmp[, 2:5] != "", na.rm =TRUE)
      

      将其转换为数据框,然后从行名转换为列,最后使用正则表达式去除不必要的字母以获得预期结果

      tmp2 <- data.frame(tmp2) %>% 
        tibble::rownames_to_column(var = "Colors") %>% 
        mutate(Colors = str_replace_all(Colors, regex("(^.*_)"), "")) %>% 
        rename(freq = tmp2)
      #   Colors freq
      # 1    Red    4
      # 2   Blue    3
      # 3  Green    3
      # 4 Purple    5
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2020-09-08
        • 2021-11-07
        • 1970-01-01
        • 1970-01-01
        • 2020-01-30
        • 1970-01-01
        • 2011-12-05
        • 2021-12-03
        相关资源
        最近更新 更多