如何使用包括 ggplot2 在内的应用函数组合多个 R 函数

How to combine multiple R functions using apply functions including ggplot2

我有一堆单独的代码块用于 运行 R 中的正态性测试,我希望能够将它们组合起来,这样我就可以测试特定变量而无需每次都复制代码。到目前为止,所有单独的代码块都在工作(以 iris 数据集为例):

library(datasets)
library(tidyverse)
library(skimr)

data(iris)
iris$Species <- NULL

# descriptive statistics and normality tests
skim(iris$Sepal.Length)
round(stat.desc(iris$Sepal.Length, basic = FALSE, norm = TRUE), digits = 3)

# histogram with normality curve
hist_sepal_length <- ggplot(iris, aes(Sepal.Length)) + 
  geom_histogram(aes(y = ..density..), bins = 10, colour = "black", fill = "white") +
  labs(x = "Sepal.Length", y = "Density") + 
  stat_function(fun = dnorm, args = list(mean = mean(iris$Sepal.Length), sd = sd(iris$Sepal.Length)), colour = "black", size = 1)
hist_sepal_length

# qqplot
qqplot_sepal_length <- qplot(sample = iris$Sepal.Length)
qqplot_sepal_length

我可以使用 sapply 做描述性统计的第一步

round(sapply(iris, stat.desc, basic = FALSE, norm = TRUE), digits = 3)

但是,我不确定如何在 ggplot2 中使用任何应用函数。我查看了以下问题:

How to use lapply with ggplot2 while indexing variables

然而,其中 none 完全涵盖了我想要的内容,因为我的 ggplot 还包括一个引用变量的 stat_function。我也想要单独图表中的输出。有没有办法编写 ggplot 代码,使其 运行 一次通过所有变量(萼片长度、萼片宽度、花瓣长度、花瓣宽度)?我有我想要 运行 常态性测试的变量已经保存到一个单独的数据框中,所以不需要子集。

最后,有没有办法将 3 个步骤(正态性检验、直方图和 qq 图)打包到一个函数中?

此处的目标是尝试在您有 Sepal.Length 通用变量时进行替换。之后,您可以创建一个函数并为每个变量调用它。然后,概括一个将 return 一次获得所有结果的循环很简单。

library(datasets)
library(tidyverse)
library(skimr)
library(pastecs)

data(iris)
#-- Function
testVarNormality <- function(var, data) {
    # descriptive statistics and normality tests
    skim_res <- skim(data[,var])
    desc_stats <- round(stat.desc(data[,var], basic = FALSE, norm = TRUE), digits = 3)

    # histogram with normality curve
    hist <- ggplot(data, aes_string(var)) + 
        geom_histogram(aes(y = ..density..), bins = 10, colour = "black", fill = "white") +
        labs(x = var, y = "Density") + 
        stat_function(fun = dnorm, args = list(mean = mean(data[,var]), sd = sd(data[,var])), colour = "black", size = 1)

    # qqplot
    qqplot <- qplot(sample = data[,var])

    list(skim_res = skim_res, desc_stats = desc_stats, histogram = hist, qqplot = qqplot)
}
#-- 1 function call
sepal_length_res <- testVarNormality("Sepal.Length", iris)
sepal_length_res$histogram
sepal_length_res$qqplot

#-- Calling for all columns (except species)
all_res <- lapply(colnames(iris)[1:4], testVarNormality, iris)
names(all_res) <- colnames(iris)[1:4]
#-- Get a result example
all_res$Sepal.Width$histogram

----

如何按物种进行:

irisBySpecies <- split(iris, iris$Species)
#-- Nested list

    res_byGroup <- lapply(
        irisBySpecies,
        function(species_data) {
            res4species <- lapply(colnames(species_data)[1:4], testVarNormality, species_data)
            names(res4species) <- colnames(iris)[1:4]
            return(res4species)
        }
    )
    names(res_byGroup) <- names(irisBySpecies)

请注意,我必须创建一个匿名函数才能执行此操作。可能有更优雅的方法来编写原始函数的代码,这样可以更容易地按组应用,但这种方法具有普遍性。