我该如何在R中对描述性统计量的列进行分组?

3

我一直在尝试使用R语言创建一个描述性统计表 - 我对这个软件还比较陌生,所以很难找到一种我想要的格式来对表格进行格式化。

目前我有以下代码:

 data %>%
      select(Gender, age, Group) %>%
      group_by(Group, Gender) %>%
      summarise(n = n(),
                age.mean = mean(age),
                age.sd = sd(age)) 

这给了我这个结果(加上均值和标准差下的数字):
  Group       Gender      age.mean    age.sd
  Group.1     Male
  Group.1     Female
  Group.1     Missing
  Group.2     Male
  Group.2     Female
  Group.2     Missing

但是这是我想要展示的方式:

                 Group.1                 Group.2
            age.mean   age.sd       age.mean   age.sd
  Male
  Female
  Missing

1
你能展示一个完整的输入示例吗? - akrun
2个回答

4

正如John所说,kable(和kableExtra)包可以帮助格式化表格,当你有分组时,还有很多其他的好功能。但是,按要求格式获得输出需要进行一些重塑。

我将使用 MASS 包中的 survey 数据集。

data(survey, package="MASS")
str(survey) # showing only a subset of vars.
'data.frame':   237 obs. of  12 variables:
 $ Sex   : Factor w/ 2 levels "Female","Male": 1 2 2 2 2 1 2 1 2 2 ...
 $ Fold  : Factor w/ 3 levels "L on R","Neither",..: 3 3 1 3 2 1 1 3 3 3 ...
 $ Age   : num  18.2 17.6 16.9 20.3 23.7 ...

The goal is to get a table similar to this:

enter image description here

library(tidyverse)
library(knitr)
library(kableExtra)

gather/spread 重新塑造数据,并将其保存以便稍后通过 kable 进行呈现。
tbl <- survey %>%
  select(Sex, Age, Fold) %>%
  filter_all(all_vars(!is.na(.))) %>%
  group_by(Fold, Sex) %>%
  summarise(n = n(),
            age.mean = sprintf("%.1f", mean(Age, na.rm=TRUE)),
            age.sd = sprintf("%.1f", sd(Age, na.rm=TRUE))) %>%
  gather(key, value, n:age.sd) %>%  #
  unite(Group, Sex, key) %>%        # Could have used pivot_wider...see below.
  spread(Group, value)              #

这将返回:

# A tibble: 3 x 7
# Groups:   Fold [3]
  Fold    Female_age.mean Female_age.sd Female_n Male_age.mean Male_age.sd Male_n
  <fct>   <chr>           <chr>         <chr>    <chr>         <chr>       <chr> 
1 L on R  21.4            9.1           48       19.6          4.0         50    
2 Neither 19.4            1.3           6        21.2          5.2         12    
3 R on L  19.7            5.0           64       20.8          7.6         56 

请注意,女性变量出现在男性变量之前。如果我使用以下代码:
pivot_wider(names_from=Sex, values_from=c(n, age.mean, age.sd))

我将得到:

# A tibble: 3 x 7
# Groups:   Fold [3]
  Fold    n_Female n_Male age.mean_Female age.mean_Male age.sd_Female age.sd_Male
  <fct>      <int>  <int> <chr>           <chr>         <chr>         <chr>      
1 L on R        48     50 21.4            19.6          9.1           4.0        
2 Neither        6     12 19.4            21.2          1.3           5.2        
3 R on L        64     56 19.7            20.8          5.0           7.6

以下序列与我们的目标不符。我可以重新排列,但使用 spread 函数能更加方便。 接下来,重新命名列名。由于 dplyr 中的 rename 函数不允许重复的名称,因此我们将使用基本 R。

tbl <- setNames(tbl, nm=sub(".+_", "", names(tbl)))

然后使用kable来应用格式。

kable(tbl, align=c('l', rep('c', 6))) %>%
  kable_styling("striped") %>%
  add_header_above(c(" " = 1, "Female" = 3, "Male" = 3))

太好了,谢谢!是否有一种简单的方法可以将额外的分组级别添加到其中?因此,如果您想要一个表格,其中包含按性别分割的n/age平均值/age sd(如上所述),但是在此基础上还要按W.Hnd分割(因此您最终会得到12列),并且还有不同变量的行(也许这更好地作为一个单独的问题提出?!) - user13343754

0

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接