R 多个变量的汇总统计信息,统计信息为行,变量为列?
我试图使用dplyr::summary()和dplyr::cross()来获得一个TIBLE,其中行中有几个摘要统计信息,列中有变量。我只能通过使用dplyr::bind_rows()来实现这个结果,但我想知道是否有更优雅的方法来获得相同的输出R 多个变量的汇总统计信息,统计信息为行,变量为列?,r,dplyr,tidyverse,summarize,across,R,Dplyr,Tidyverse,Summarize,Across,我试图使用dplyr::summary()和dplyr::cross()来获得一个TIBLE,其中行中有几个摘要统计信息,列中有变量。我只能通过使用dplyr::bind_rows()来实现这个结果,但我想知道是否有更优雅的方法来获得相同的输出 > library(tidyverse) ── Attaching packages ────────────────────────────────────────────── tidyverse 1.3.1 ── ✔ ggplot2 3.3.3
> library(tidyverse)
── Attaching packages ────────────────────────────────────────────── tidyverse 1.3.1 ──
✔ ggplot2 3.3.3 ✔ purrr 0.3.4
✔ tibble 3.1.1 ✔ dplyr 1.0.6
✔ tidyr 1.1.3 ✔ stringr 1.4.0
✔ readr 1.4.0 ✔ forcats 0.5.1
── Conflicts ───────────────────────────────────────────────── tidyverse_conflicts() ──
✖ dplyr::filter() masks stats::filter()
✖ dplyr::lag() masks stats::lag()
>
> bind_rows(min = summarize(starwars, across(where(is.numeric), min,
+ na.rm = TRUE)),
+ median = summarize(starwars, across(where(is.numeric), median,
+ na.rm = TRUE)),
+ mean = summarize(starwars, across(where(is.numeric), mean, na.rm = TRUE)),
+ max = summarize(starwars, across(where(is.numeric), max, na.rm = TRUE)),
+ sd = summarize(starwars, across(where(is.numeric), sd, na.rm = TRUE)),
+ .id = "statistic")
# A tibble: 5 x 4
statistic height mass birth_year
<chr> <dbl> <dbl> <dbl>
1 min 66 15 8
2 median 180 79 52
3 mean 174. 97.3 87.6
4 max 264 1358 896
5 sd 34.8 169. 155.
>库(tidyverse)
── 附加包────────────────────────────────────────────── tidyverse 1.3.1──
✔ GG2.3.3✔ purrr 0.3.4
✔ tibble 3.1.1✔ dplyr 1.0.6
✔ 第1.1.3节✔ stringr 1.4.0
✔ readr 1.4.0✔ 猫类0.5.1
── 冲突───────────────────────────────────────────────── tidyverse_冲突()──
✖ dplyr::filter()屏蔽stats::filter()
✖ dplyr::lag()屏蔽stats::lag()
>
>bind_行(min=summary(星战、跨越)(其中(是数字)、min、,
+na.rm=真),
+中位数=汇总(星战、跨越(其中(是数字)、中位数、,
+na.rm=真),
+平均值=汇总(星战,跨越(其中(为数字),平均值,na.rm=真)),
+max=summary(starwars,cross(其中(is.numeric),max,na.rm=TRUE)),
+sd=汇总(星战,跨越(其中(是数字的),sd,na.rm=真的)),
+.id=“统计”)
#一个tibble:5x4
人口出生年统计高度
1分钟66 15 8
2中位数180 79 52
3平均174。97.3 87.6
4最大264 1358 896
5 sd 34.8 169。155
为什么一个人不能直接用它来做呢?似乎比使用函数列表更优雅,正如。这是否违反了整洁数据框架的原则?(在我看来,将一堆数据帧相互堆叠起来要不那么整齐。)这可以在您想要的输出中解决,但这并不是那么花哨
starwars %>%
summarise(across(
where(is.numeric),
.fns = list(
min = min,
median = median,
mean = mean,
max = max,
sd = sd
),
na.rm = TRUE,
.names = "{.col}_{.fn}")) %>%
pivot_longer(cols = everything()) %>%
mutate(statistic = str_match(name, pattern = ".+_(.+)")[,2],
name = str_match(name, pattern = "(.+)_.+")[,2]) %>%
pivot_wider(names_from = name, values_from = value)
您可以使用
gtsummary
汇总数据。下面是数字列的子集(尽管gtsummary
处理许多不同的数据类型。然后我告诉type参数将我的摘要统计信息放在不同的行上,最后告诉statistics参数我要显示哪些摘要
library(tidyverse)
library(gtsummary)
starwars[sapply(starwars, is.numeric)] %>%
tbl_summary(type = all_continuous() ~ "continuous2",
statistic = all_continuous() ~ c("{median} ({p25}, {p75})",
"{min}, {max}",
"{mean},{sd}"))
我会这样做:
starwars %>%
summarise(across(where(is.numeric), stat_funs,
na.rm = TRUE, .names = "{.col}__{.fn}")) %>%
pivot_longer(everything()) %>%
separate(name, c('v', 'f'), sep = '__') %>%
pivot_wider(names_from = v, values_from = value)
# f height mass birth_year
# <chr> <dbl> <dbl> <dbl>
# 1 min 66 15 8
# 2 median 180 79 52
# 3 mean 174. 97.3 87.6
# 4 max 264 1358 896
# 5 sd 34.8 169. 155.
starwars%>%
总结(跨越(其中(为数字)、统计数据、,
na.rm=TRUE,.names=“{.col}{.fn}”))%>%
pivot_更长(所有内容())%>%
单独的(名称,c('v','f'),sep=''.'''.''>%
枢轴(名称从=v,值从=value)
#f身高出生年月
#
#1分钟66 15 8
#2中位数180 79 52
#3平均174.97.387.6
#4最大264 1358 896
#5 sd 34.8169.155。
下面是一种使用purr
迭代函数列表的方法。这是您使用bind_rows()
进行的有效操作,但代码较少
库(dplyr)
图书馆(purrr)
funs我想说,这与@mt1022的解决方案在本质上是相同的,这是正确的,我更喜欢他的解决方案。您所需输出中的每一行都有不同的定义。第1行是最小值,第2行是中值,等等。因此,虽然这可能很方便使用,但您不会对该输出的整列进行操作(例如,您不会对高度求和).所以我不确定输出是否整洁。总结
为您提供广泛输出的方式可能更“整洁”,但我理解你为什么要这样处理它。很多都是哲学,只是理解你试图用数据做什么。这是一个很好的观点。你认为如果我在行中有变量,在列中有统计数据会更整洁吗?这对于表示的目的也很好。你想存储和处理数据吗以整洁的格式。对于演示,做最能传达信息的事情。你拥有的东西可能适合演示。我不会过分强调让你的演示表“整洁”。很好的解决方案和优雅的使用lst
+maf\u dfr
。我经常注意到,map_*函数用于使事情变得比必要的更复杂。事实并非如此。