如何使用包括 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)
请注意,我必须创建一个匿名函数才能执行此操作。可能有更优雅的方法来编写原始函数的代码,这样可以更容易地按组应用,但这种方法具有普遍性。
我有一堆单独的代码块用于 运行 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)
请注意,我必须创建一个匿名函数才能执行此操作。可能有更优雅的方法来编写原始函数的代码,这样可以更容易地按组应用,但这种方法具有普遍性。