【问题标题】:Create table of means and (standard deviations) for multiple variables, by groups, formatted for publication为多个变量创建均值和(标准差)表,按组,格式化以供发布
【发布时间】:2017-06-19 02:51:07
【问题描述】:

我正在学习 R。我想使用简单易读的 R 代码为出版物生成汇总统计表。该表应将变量作为行,将交替平均值和 SD 作为列,并将两个分组变量也作为列。所有值都应四舍五入为两位数,包括零(必要时添加零)。

以 mtcars 数据集为例,我希望表格看起来像这样比较 4、6 和 8 缸汽车,自动或手动):

|     |4 0       |        |4 1       |        |6 0       |        |6 1       |        |8 0       |        |8 1       |        |
|:----|:---------|:-------|:---------|:-------|:---------|:-------|:---------|:-------|:---------|:-------|:---------|:-------|
|     |mean      |(SD)    |mean      |(SD)    |mean      |(SD)    |mean      |(SD)    |mean      |(SD)    |mean      |(SD)    |
|mpg  |22.90     |(1.45)  |28.07     |(4.48)  |19.12     |(1.63)  |20.57     |(0.75)  |15.05     |(2.77)  |15.40     |(0.57)  |
|disp |135.87    |(13.97) |93.61     |(20.48) |204.55    |(44.74) |155.00    |(8.66)  |357.62    |(71.82) |326.00    |(35.36) |
|hp   |84.67     |(19.66) |81.88     |(22.66) |115.25    |(9.18)  |131.67    |(37.53) |194.17    |(33.36) |299.50    |(50.20) |

我编写了以下代码,但我仍然需要创建前两行,并将括号添加到 SD 列。为了使表格更便于发布,我使用了 R Markdown、knitr 和 kable。有没有更简单、更标准或更惯用的方法呢?

```{r Create-Table-1}
library(data.table)
library(knitr)

mtcars_dt <- data.table(mtcars)
myGroups <- c("cyl", "am")
myVariables <- c("mpg", "disp", "hp")

means_dt <- mtcars_dt[,lapply(.SD, mean), .SDcols = myVariables, by = myGroups]
means_dt.melted <- melt.data.table(means_dt, id.vars = myGroups, measure.vars = myVariables)
means_dt.melted$stat <- "mean"

sd_dt <- mtcars_dt[,lapply(.SD, sd), .SDcols=myVariables, by=myGroups]
sd_dt.melted <- melt.data.table(sd_dt, id.vars = myGroups, measure.vars = myVariables)
sd_dt.melted$stat <- "sd" 

means_sd_merged_dt <- rbindlist(list(means_dt.melted, sd_dt.melted))
means_sd_dt <- dcast.data.table(means_sd_merged_dt, variable ~ cyl + am + stat, value.var = "value")

kable(means_sd_dt, digits = 2)

```

这是代码生成的表格。 “8_1_mean”列未正确舍入。我试过pander,但它不能加零。

|variable | 4_0_mean| 4_0_sd| 4_1_mean| 4_1_sd| 6_0_mean| 6_0_sd| 6_1_mean| 6_1_sd| 8_0_mean| 8_0_sd| 8_1_mean| 8_1_sd|
|:--------|--------:|------:|--------:|------:|--------:|------:|--------:|------:|--------:|------:|--------:|------:|
|mpg      |    22.90|   1.45|    28.07|   4.48|    19.12|   1.63|    20.57|   0.75|    15.05|   2.77|     15.4|   0.57|
|disp     |   135.87|  13.97|    93.61|  20.48|   204.55|  44.74|   155.00|   8.66|   357.62|  71.82|    326.0|  35.36|
|hp       |    84.67|  19.66|    81.88|  22.66|   115.25|   9.18|   131.67|  37.53|   194.17|  33.36|    299.5|  50.20|

更新: 我发布这个问题的主要原因之一是看看是否有更简单的方法来制作这种表格,使用其他库和编程最佳实践。

但是,chinsoon12 提供了一个有效的答案,我将其合并到我在 R 中的第一个函数中。我在这里更新,以便其他人可以修改和使用该函数。它仍然有一个我无法用数字和/或 nsmall 确定的错误,有时子组的数字会比指定的多一个。

tabulatemsg <- function(variables, groups, input_dt, round_digits = 2, na.rm = FALSE) {
  # Create a table of alternating means and (SDs), for the specified variables, with groups as columns.
  require(data.table)

  # Aggregate means
  means_dt <- input_dt[,lapply(.SD, mean, na.rm = na.rm), .SDcols = variables, by = groups]
  means_dt.melted <- melt.data.table(means_dt, id.vars = groups, measure.vars = variables)
  means_dt.melted$stat <- "mean"

  # Aggregate standard deviations
  sd_dt <- input_dt[,lapply(.SD, sd, na.rm = na.rm), .SDcols=variables, by=groups]
  sd_dt.melted <- melt.data.table(sd_dt, id.vars = groups, measure.vars = variables)
  sd_dt.melted$stat <- "sd" 

  # Merge and cast
  means_sd_merged_dt <- rbindlist(list(means_dt.melted, sd_dt.melted))
  means_sd_dt <- dcast.data.table(means_sd_merged_dt, paste("variable", 
    paste(c(groups, "stat"), collapse=" + "), sep=" ~ "), value.var = "value")

  # Ensure there are the specified number of digits after the decimal
  cols <- setdiff(names(means_sd_dt), "variable")
  means_sd_dt[, (cols) := lapply(.SD, format, digits=round_digits, nsmall=round_digits, justify="none"), .SDcols=cols]
  means_sd_dt[, (cols) := lapply(.SD, trimws), .SDcols=cols]

  # Add in parentheses
  cols <- names(means_sd_dt)[seq(3, ncol(means_sd_dt), by=2)]
  means_sd_dt[, (cols) := lapply(.SD, function(x) paste0("(", x, ")")), .SDcols=cols]

  # Add in second row
  output_table <- rbindlist(list(
    data.table(t(c("", rep(c("Mean", "(SD)"), (ncol(means_sd_dt)-1)/2)))),
    means_sd_dt), use.names=FALSE)

  # Rename first row
  setnames(output_table, colnames(output_table), 
    gsub("variable", "", (gsub(" sd","", (gsub(" mean", "", (gsub("_"," ", colnames(means_sd_dt)))))))))

  return(output_table)
}

【问题讨论】:

    标签: r data.table knitr r-markdown aggregation


    【解决方案1】:

    您可以使用format将每一列转换为字符类,这样您就可以确保小数点后有2位数字,然后添加括号

    #ensure there are 2 digits after decimal
    cols <- setdiff(names(means_sd_dt), "variable")
    means_sd_dt[, (cols) := lapply(.SD, format, digits=2, nsmall=2L, justify="none"), .SDcols=cols]
    means_sd_dt[, (cols) := lapply(.SD, trimws), .SDcols=cols]
    
    #add in parentheses
    cols <- names(means_sd_dt)[seq(3, ncol(means_sd_dt), by=2)]
    means_sd_dt[, (cols) := lapply(.SD, function(x) paste0("(", x, ")")), .SDcols=cols]
    
    #add in first row
    outputTbl <- rbindlist(list(
        data.table(t(c("", rep(c("mean", "(SD)"), (ncol(means_sd_dt)-1)/2)))),
        means_sd_dt), use.names=FALSE)
    
    kable(outputTbl, digits = 2)
    

    【讨论】:

    • 这很有帮助,谢谢!我也想出了如何修复列名行。 #rename columns setnames(outputTbl, colnames(outputTbl), gsub("variable", "", (gsub(" sd", "", (gsub(" mean", "", (gsub("_", " ", colnames(means_sd_dt)))))))))
    • 我想把它变成一个函数,这样我就可以将它用于各种出版物。有没有办法修复 means_sd_dt &lt;- dcast.data.table(means_sd_merged_dt, variable ~ cyl + am + stat, value.var = "value") 行,使其引用 myCols 而不是手动指定它们?
    • 现在不在R前面,看看'as.formula'。
    • 谢谢,我找到了this page,从中我可以得到更正的行:means_sd_dt &lt;- dcast.data.table(means_sd_merged_dt, paste("variable", paste(c(myGroups, "stat"), collapse=" + "), sep=" ~ "), value.var = "value")
    猜你喜欢
    • 1970-01-01
    • 2013-04-28
    • 2021-12-30
    • 2020-09-15
    • 1970-01-01
    • 2020-08-08
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多