【问题标题】:Frequency Table of Categorical Variables as a Data Frame in R分类变量的频率表作为 R 中的数据框
【发布时间】:2020-08-12 22:08:34
【问题描述】:

我想在 R 中创建所有分类变量的频率表作为数据框。我想找到每个调查响应的频率和百分比(按条件分组,以及总频率)。我想将其生成为数据框。

仅针对一个变量(“q1”)的所需频率计数的示例。我希望数据中的大多数变量具有类似的频率计数:

我有这样的数据。实际数据有更多的分类变量。

library(readr)
data_in <- read_table2("treatment_cur   q13_3   q14_1   q14_2   q14_3   q14_4   q14_5   q14_6   q14_7   q14_8   q14_9   q14_10  q14_11  q14_12  q14_13  q14_14  q14_15
Control 3   2   3   6   5   6   6   6   4   5   5   5   4   6   6   5
Control 2   4   5   6   5   6   5   5   6   4   5   5   6   5   4   6
Treatment   3   1   2   6   4   6   5   4   6   4   6   1   5   6   4   6
Control 3   2   3   6   4   6   6   6   6   6   6   6   6   5   5   6
Control NA  NA  NA  NA  NA  NA  NA  NA  NA  NA  NA  NA  NA  NA  NA  NA
Control 4   6   5   6   5   6   5   6   6   5   1   1   6   5   5   6
Control 3   3   2   2   3   3   6   6   4   6   5   5   3   6   6   2
Treatment   2   3   2   3   1   3   1   1   1   3   3   3   3   3   3   1
Control 3   5   5   6   3   6   3   3   3   2   2   1   4   2   3   4
Control 2   1   1   1   1   1   4   4   1   1   1   1   1   4   4   2
Control 4   3   4   6   6   6   6   6   6   6   6   6   6   6   6   6
Control 4   2   6   6   4   6   5   6   6   5   6   5   6   6   6   6
Control 2   2   3   3   2   3   5   6   5   3   3   3   3   5   3   2
Control 3   2   4   3   4   5   4   4   5   3   3   5   4   5   5   4
Treatment   2   2   2   2   2   3   1   1   2   2   3   2   3   3   2   3
Control 4   3   3   3   5   6   6   6   6   6   6   6   6   6   6   6
Treatment   2   1   3   3   2   1   3   4   2   2   3   3   2   3   3   3
Treatment   4   2   6   4   4   2   3   5   4   5   1   1   5   4   4   5
Control 3   3   3   4   4   4   4   5   3   2   5   4   5   5   4   4
Control 4   6   6   6   6   6   6   6   6   6   6   6   5   6   6   5
Control 2   2   3   6   2   5   1   2   4   4   1   1   6   4   4   6
Treatment   4   3   3   6   6   6   6   6   6   6   6   6   6   6   6   6
Treatment   4   6   6   6   6   6   6   6   6   6   6   6   6   6   6   6
Treatment   1   1   2   4   4   4   1   1   1   1   1   1   6   1   1   6
Treatment   3   2   3   3   2   6   6   6   6   3   3   2   4   5   5   6
Control 2   1   1   1   1   1   1   2   1   1   1   1   1   2   2   1
Control 1   3   3   3   1   1   5   5   2   4   5   5   4   1   2   5
Treatment   3   4   4   5   5   4   4   4   3   5   3   4   4   6   6   5
Control NA  NA  NA  NA  NA  NA  NA  NA  NA  NA  NA  NA  NA  NA  NA  NA
Control 2   2   4   6   2   4   2   2   3   5   4   4   4   3   3   5
Treatment   1   1   2   1   1   1   1   1   6   1   1   1   6   2   3   6
Treatment   2   6   1   4   4   1   1   2   2   2   1   2   1   2   2   2
Treatment   3   3   4   4   4   6   6   5   4   6   3   5   5   6   6   4
Treatment   2   1   3   3   3   3   3   3   3   3   3   3   3   3   3   3
Control 4   3   4   6   4   6   4   5   6   3   4   4   6   6   4   6
Control 4   4   3   6   2   5   2   2   4   3   1   6   5   5   5   5
Control NA  NA  NA  NA  NA  NA  NA  NA  NA  NA  NA  NA  NA  NA  NA  NA
Treatment   2   3   3   6   5   6   1   2   6   5   4   4   5   5   5   6
Control 4   6   6   6   6   6   5   5   5   5   5   6   5   5   5   5
Treatment   2   1   1   3   1   3   4   4   4   4   1   4   3   4   4   4
Treatment   2   1   3   3   3   3   4   6   5   4   5   5   4   6   6   5
Control 4   6   6   6   6   6   5   5   5   6   6   5   5   5   6   6
Control NA  NA  NA  NA  NA  NA  NA  NA  NA  NA  NA  NA  NA  NA  NA  NA
Control 4   2   2   4   2   4   6   6   6   6   4   6   5   6   6   5
Control 1   1   1   1   1   1   1   1   1   1   1   1   1   1   1   1
Treatment   3   4   2   5   5   5   6   5   5   5   5   5   5   6   6   6
Control NA  2   4   4   4   4   4   3   4   6   4   5   4   6   4   4
Control 2   2   2   3   1   3   4   1   1   1   2   1   3   3   3   3
Treatment   2   2   2   3   2   2   3   3   2   2   2   2   2   2   2   2
Control 3   3   3   6   6   6   6   6   6   6   5   6   6   6   6   6
Treatment   2   1   2   2   2   1   2   2   1   1   2   1   2   2   1   3
Treatment   4   5   5   6   6   5   5   6   5   5   4   5   5   4   4   5
Control 3   2   2   2   2   2   2   2   2   2   2   2   2   2   2   2
Treatment   3   3   4   4   4   6   3   2   5   3   2   2   5   6   5   6
Control 4   4   3   3   6   3   6   6   3   2   4   4   4   4   4   4
Treatment   4   1   3   4   4   4   5   6   6   6   6   6   6   6   6   6
Control 4   4   5   6   5   5   4   6   6   6   6   5   6   6   6   6
Treatment   3   3   4   6   6   6   6   6   5   6   6   5   4   6   6   4
Control 4   4   6   6   4   6   6   6   6   4   4   3   5   6   6   6
Control 4   6   6   6   6   6   6   6   6   6   6   6   6   6   6   6
Treatment   4   5   5   6   6   6   6   6   5   5   6   6   5   5   6   6
Treatment   4   6   6   6   6   6   6   6   6   6   6   6   6   6   6   6
Control 2   1   2   1   1   1   1   3   1   4   4   1   1   1   1   1
Treatment   1   1   1   1   1   1   1   1   1   1   1   1   1   1   1   1
Treatment   4   6   5   5   5   5   5   6   5   4   5   4   4   5   5   4
Treatment   4   6   6   6   6   6   6   6   6   6   6   6   6   6   6   6
Control 4   4   4   4   4   4   4   4   4   4   4   4   4   4   4   4
Treatment   4   5   6   6   6   5   6   6   6   5   6   6   6   6   6   6
Control 2   2   2   2   2   2   2   2   2   2   2   2   2   2   2   2
Treatment   3   3   2   5   4   4   5   6   6   4   5   5   4   5   4   6
Treatment   4   5   4   4   4   5   5   6   4   5   4   3   6   6   6   6
Control 1   2   3   2   1   4   1   1   3   1   3   3   3   3   4   4
Control 3   6   6   6   6   6   5   1   5   6   5   6   6   6   6   6
Control 1   1   1   1   1   1   1   1   1   1   1   1   1   1   1   1
Control 4   2   2   2   2   2   2   2   2   2   2   2   2   2   2   2
")

我目前的解决方案太复杂了。如果我想知道 q13_3:q14_9 中变量的频率,我知道我可以这样做来找到它:

library(tables)
varList <- 2:11
data_in[varList] <- lapply(data_in[varList], factor,exclude = NULL)

  lapply(varList,function(x,df,byVar){ 
    tabular((Factor(df[[x]],paste(colnames(df)[x])) + 1) ~ ((Factor(df[[byVar]],paste(byVar)))*((n=1) + Percent("col"))),
            data= df) 
  },data_in,"treatment_cur") 

下面是我当前输出的 sn-p。问题是输出是无法导出到单个 Excel 工作表中的列表列表。我必须手动将控制台中的所有内容复制到 Excel 文件中。

       treatment_cur                          
       Control               Treatment        
 q14_8 n             Percent n         Percent
 1      6             13.953  4         12.50 
 2      4              9.302  4         12.50 
 3      5             11.628  2          6.25 
 4      6             13.953  4         12.50 
 5      5             11.628  7         21.88 
 6     13             30.233 11         34.38 
 NA     4              9.302  0          0.00 
 All   43            100.000 32        100.00 

[[10]]
                                              
       treatment_cur                          
       Control               Treatment        
 q14_9 n             Percent n         Percent
 1      6             13.953  4         12.50 
 2      6             13.953  4         12.50 
 3      4              9.302  4         12.50 
 4      6             13.953  5         15.62 
 5      5             11.628  8         25.00 
 6     12             27.907  7         21.88 
 NA     4              9.302  0          0.00 
 All   43            100.000 32        10

这没问题,但我想:

  1. 找出每个变量值的总频率(治疗 + 条件)作为附加列(如上图所示);
  2. 我不喜欢用于生成此输出的函数。我想将它导出到一个 excel 文件中,但由于这个输出实际上是一个列表列表(它不能导出到 excel),我发现将这些值从控制台复制并粘贴到 excel 中非常麻烦。我想要一种更简单的方法来找到这些频率!当然,R 有更好的方法来做到这一点......

非常感谢任何帮助!

【问题讨论】:

    标签: r dplyr tidyverse


    【解决方案1】:

    一种方法是使用gtsummary 包进行探索。

    使用上面的代码,您可以很容易地生成一个包含计数和百分比的表格:

    library(gtsummary)
    library(readr)
    library(flextable)
    
    
    tbl_summary(data_in, by = "treatment_cur") %>% 
        add_overall() %>% 
        as_flex_table() %>% 
        flextable::save_as_docx(., path = "G:/test.docx")
    

    如果你只是运行:

    tbl_summary(data_in, by = "treatment_cur") %>% 
            add_overall()
    

    您将看到它为您生成的表格。之后的额外代码使其能够导出到 docx 文件。从那里您可以将其复制到excel中。这会生成您请求的计数,您可以确定它是否是一个更简单的实现。

    另一种选择是直接写入 csv 文件:

    tbl_summary(data_in, by = "treatment_cur") %>% 
        add_overall() %>% 
        as_tibble() %>% 
        readr::write_csv( .,path = "G:/test.csv")
    

    或 如果您真的需要单独列中的所有内容,您可以将 n 和 percents 分成两个表,合并它们,然后写入 csv。

    #keep counts only
    ncount <- tbl_summary(data_in, by = "treatment_cur",
                statistic = all_categorical()~ "{n}") %>% 
        add_overall() 
    
    #keep pcts only
    
    pctdata <- tbl_summary(data_in, by = "treatment_cur",
                statistic = all_categorical()~ "{p}%") %>% 
      add_overall() 
    #combine and output
    
    tbl_merge(list(ncount, pctdata)) %>% 
          as_tibble() %>% 
          readr::write_csv(., "G:/test2.csv")
    

    编辑: 另一种解决方法是使用 janitor 包。您可以很容易地修饰计数和百分比并将数据集合并在一起。之后很容易导出到 csv/Excel。这里的一个缺点是您必须遍历变量以获取每个变量的表,然后将它们组合在一起,但是下面的代码是创建它的良好开端:

    library(janitor)
    
    
    datatry <- data_in %>% 
              janitor::tabyl( q13_3,treatment_cur) %>% 
              adorn_totals("col") %>% 
              adorn_totals("row")
    
    datatry2 <- data_in %>% 
      janitor::tabyl( q13_3,treatment_cur) %>% 
      janitor::adorn_percentages(denominator = 'col') %>% 
      adorn_totals("row") %>% 
      adorn_totals("col") %>% 
      mutate(Total = ifelse(is.na(q13_3), Total, ifelse(q13_3 == 'Total',1, Total)))
    
    datatry3 <- inner_join(datatry, datatry2, by = 'q13_3') %>%
                mutate(variable ='q13_3')
    

    【讨论】:

    • 谢谢@Mike。这真的很接近我想要的!我还需要查看每个问题的每列的“总计”。现在,我必须读出 tibble 并重新读入以计算总数。 (tbl_merge 的列名是相同的,所以我不能直接操作它)。
    • 问题/变量名称与它们的值在同一列中,因此我无法操作 tibble/dataframe 以按问题分组并找到总数。
    • @NewBee 总数在标题列中,而不是在它自己的单独行中。您是否需要总数,因为它会根据缺失值而变化?您希望如何处理包含或排除在表中的缺失值?如果有帮助,我也可以更改列的标签。
    • @NewBee 默认是 gtsummary 不将未知值包含在百分比中
    • 您可以将 tbl_summary 中缺少的选项更改为“始终”,以便将它们包含在 %s 中,我更新了答案
    【解决方案2】:

    假设您如上所述构造了data_in

    library(dplyr)
    library(purrr)
    
    # reformat
    tt <- data_in$treatment_cur
    data_in$treatment_cur <- NULL
    
    data_in %>% map(function(a)
    {
        ret <- data.frame(Treatment.n=rep(0, 6), Control.n=rep(0, 6))
        b <- table(a[tt=="Treatment"])
        ret[names(b), "Treatment.n"] <- b
        b <- table(a[tt=="Control"])
        ret[names(b), "Control.n"] <- b
        ret$Treatment.percent <- ret$Treatment.n / sum(ret$Treatment.n)
        ret$Control.percent <- ret$Control.n / sum(ret$Control.n)
        ret
    }) %>% do.call(what=cbind)
    

    假设答案数据是 \in 1..6 并且 NA 被忽略。

    【讨论】:

    • 谢谢,这很有用!我确实想要一个不涉及函数的答案..所以我将把答案奖励给建议 tbl_summary 的人。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-05-04
    • 1970-01-01
    • 2020-04-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-01-24
    相关资源
    最近更新 更多