'x' 在 curve/dnorm 中做了什么,为什么它在我的函数中起作用?

What does 'x' do in curve/dnorm, and why does it work in my function?

我正在制作一个函数 Prop.Histogram(),它将数据绘制为直方图,显示添加了正态分布曲线的比例。添加曲线对我来说很难实现,但我成功了(见下面的代码)!

注意:我个人更喜欢在我的代码中使用 magrittr 包中的管道运算符 %>%。虽然,可能不是每个人都熟悉这个运算符 and/or 这个包(或者他们不想使用它),但我也会在下面提供不使用 magrittr 的相同代码。

代码使用 magrittr

Prop.Histogram <- function(data,
   xlim_min, xlim_max, x_BreakSize,
   ylim_max, y_steps) {

# Load packages
library(magrittr)

# Make histogram of data without y-axis
hist(data, freq = FALSE, ylab = "Proportion",
   xlim = c(xlim_min, xlim_max), breaks = seq(from = xlim_min, to = xlim_max, by = x_BreakSize),
   ylim = c(0, ylim_max %>% divide_by(., x_BreakSize)), yaxt = "n")

# I divided ylim_max by x_BreakSize, as I want ylim_max to be equal to the max proportion shown on the y_axis (and not to the max density)

# Add y-axis that shows proportion and not density
axis(side = 2,
   at = seq(from = 0, to = ylim_max %>% divide_by(., x_BreakSize), by = y_steps %>% divide_by(., x_BreakSize)),
   labels = seq(from = 0, to = ylim_max, by = y_steps))

box()

# Add curve to histogram
curve(dnorm(x, mean = mean(data), sd = sd(data)), lwd = 5, add = TRUE, yaxt = "n")

}

不使用 magrittr 的相同代码

Prop.Histogram <- function(data,
   xlim_min, xlim_max, x_BreakSize,
   ylim_max, y_steps) {

# Load packages
library(magrittr)

# Make histogram of data without y-axis
hist(data, freq = FALSE, ylab = "Proportion",
   xlim = c(xlim_min, xlim_max), breaks = seq(from = xlim_min, to = xlim_max, by = x_BreakSize),
   ylim = c(0, ylim_max/x_BreakSize), yaxt = "n")

# I divided ylim_max by x_BreakSize, as I want ylim_max to be equal to the max proportion shown on the y_axis (and not to the max density)

# Add y-axis that shows proportion and not density
axis(side = 2,
   at = seq(from = 0, to = ylim_max/x_BreakSize, by = y_steps/x_BreakSize),
   labels = seq(from = 0, to = ylim_max, by = y_steps))

box()

# Add curve to histogram
curve(dnorm(x, mean = mean(data), sd = sd(data)), lwd = 5, add = TRUE, yaxt = "n")

}

此代码完全符合我的要求:绘制比例图并向图中添加一条正态分布曲线。虽然,我确实很难理解为什么添加曲线实际上有效。

主要问题(1):我必须将x作为dnorm()中的第一个参数,即使我没有定义x,有效!所以我的第一个也是主要问题是:什么是 x,它有什么作用,为什么它在我的函数中起作用?

第二个问题(2):我的第二个问题是是否可以(如果可以,如何)使用 magrittr pipe-operators (%>%)在将曲线添加到绘图的代码行中。 (即使在这种情况下使用运算符不是最好的方法,我仍然对答案感兴趣,因为我渴望学习!)


首先,对于那些想尝试我的代码的人:这里有一些数据代表我想要绘制的数据:

data <- rnorm(724, mean = 84, sd = 33)
Prop.Histogram(data,
               xlim_min = -50, xlim_max = 200, x_BreakSize = 10,
               ylim_max = 0.15, y_step = 0.05)

主要问题(1)xdnorm()/curve()

中的作用

我开始使用 data 而不是 x 作为 dnorm() 的第一个参数,但这没有用,因为它导致了以下错误消息:

   Error in curve(dnorm(data, mean = mean(data), sd = sd(data)), lwd = 5,  :
   'expr' must be a function, or a call or an expression containing 'x'

但是,当我单独取 dnorm(data, mean = mean(data), sd = sd(data)) 和 运行 时(不是作为 curve() 的参数,它给了我 724 个值(我不知道是什么他们的意思是,但至少它不是错误消息。这很奇怪,因为在我的公式中使用 data 作为第一个参数时 dnorm()curve 的一部分会导致错误消息正如我们之前看到的。

然后,当我将 data 更改为 x 和 运行 dnorm(x, mean = mean(data), sd = sd(data))(同样不是 curve() 的参数)时,它给了我另一个错误信息:

   Error in dnorm(x, mean = mean(data), sd = sd(data)) :
   object 'x' not found

这我能理解,因为我没有在我的代码中的任何地方定义 x。但这引发了一个问题:为什么当我 运行 我的(工作)功能时我没有收到同样的错误消息。

简而言之,我观察到 x 必须是 dnorm() 中的第一个参数,当 dnorm() 用作 curve() 中的参数时,但是 x 不能用作单独使用 dnorm() 时的第一个参数。结论:我迷路了。

当然,当我在R中迷路时,我总是看R的帮助页面。dnorm()的帮助页面指出x是分位数的向量...那是它。我分别知道这些词,但不知道它在我的代码中意味着什么(因为我没有定义 x,所以 R 帮助页面谈论的是什么向量或什么分位数?)。


第二题(2): magrittr在代码中的使用

我尝试使用 magrittr 编写代码 curve(dnorm(x, mean = mean(data), sd = sd(data)), lwd = 5, add = TRUE, yaxt = "n"),但它不起作用。以下是我尝试过的一些示例:

data %>% dnorm(x, mean = mean(.), sd = sd(.)) %>% curve(., lwd = 5, add = TRUE, yaxt = "n")
data %>% dnorm(x, mean = mean(.), sd = sd(.)) %>% curve(lwd = 5, add = TRUE, yaxt = "n")
dnorm(x, mean = mean(data), sd = sd(data)) %>% curve(., lwd = 5, add = TRUE, yaxt = "n")

它们都导致相同的错误消息:

  Error in dnorm(x, mean = mean(data), sd = sd(data)) : 
  object 'x' not found

我想知道在这种情况下是否可以使用像 %>% 这样的 magrittr 运算符(即使它不是最佳选择)。


PS。这是我第一次发帖,所以请随时提供反馈或在需要时向我询问更多信息。提前致谢!

curve() 函数使用 non-standard 求值。 x 只是它将绘制的表达式中的占位符。有关详细信息,请参阅 ?curve

事实上,x 不必是第一个参数,它可以出现在表达式的任何位置。但是你会希望它附加到 dnorm 的第一个参数,所以把它放在前面效果很好。如果您想查看 sd 参数对 0 处密度的影响,您可以使用

curve(dnorm(0, sd = x))

当你把它放在第一位时,curve() 正在寻找的虚拟 x 将绑定到 dnorm() 的第一个参数,它恰好也被命名为 x,正如您在帮助页面上看到的那样。就是你要计算密度的位置。

当您调用 dnorm(data, mean = mean(data), sd = sd(data)) 时,您要求它计算正态分布的密度,均值 mean(data) 和标准差 sd(data) 每个 data 中的位置。这就是为什么您得到长矢量响应的原因。

对于你的第二个问题:magrittr将管道左侧的结果传递给右侧的函数调用。这些结果出现的位置有一些复杂的规则:

  1. 如果在函数调用中不使用 .,则该值用作第一个参数。

  2. 如果您使用 .,参数会出现在那里,但也可能出现在第一位。我忘记了确切的规则;有关详细信息,请参阅 ?pipe

所以要得到你想要的,你可以这样做:

data %>% {curve(dnorm(x, mean = mean(.), sd = sd(.), lwd = 5, add = TRUE, yaxt = "n")}

我不得不使用大括号来获取 magrittr 以正确处理 .