同时对向量及其元素进行操作的函数如何在R中起作用?

时间:2013-03-04 15:50:25

标签: r

采用以下示例:

boltzmann <- function(x, t=0.1) { exp(x/t) / sum(exp(x/t)) }
z=rnorm(10,mean=1,sd=0.5)
exp(z[1]/t)/sum(exp(z/t))
[1] 0.0006599707
boltzmann(z)[1]
[1] 0.0006599707

exp函数中的boltzmann似乎对元素和向量进行操作,并知道何时做正确的事情。 sum“展开”输入向量并在值上应用表达式吗?有人可以解释这在R中是如何工作的吗?

编辑:感谢您对R n00b的所有评论,澄清和耐心。总之,对于我来自其他语言的原因,这个原因并不是很明显。以python为例。您首先计算总和,然后计算向量中每个元素的值。

denom = sum([exp(v / t) for v in x])
vals = [exp(v / t) / denom for v in x]

而R是sum(exp(x/t))可以内联计算。

3 个答案:

答案 0 :(得分:4)

An Introduction to RSection 2.2: Vector arithmetic中解释了这一点。

  

矢量可用于算术表达式,在这种情况下   操作是逐个元素执行的。载体中出现的载体   相同的表达不需要都具有相同的长度。如果他们不是,   表达式的值是一个与长度相同的向量   表达式中出现的最长向量。更短的向量   表达式回收根据需要(可能是分数)   直到它们匹配最长矢量的长度。特别是a   常数只是重复。所以使用上面的赋值命令

x <- c(10.4, 5.6, 3.1, 6.4, 21.7)
y <- c(x, 0, x)
v <- 2*x + y + 1
     

生成一个长度为11的新向量v,通过加在一起构造,   元素逐元素,2 * x重复2.2次,y重复一次,然后   1次重复11次。

答案 1 :(得分:3)

如果分别评估分子和分母,这可能会更清楚:

x = rnorm(10,mean=1,sd=0.5)
t = .1
exp(x/t)
# [1] 1.845179e+05 6.679273e+03 4.379369e+06 1.852623e+06 9.960374e+02
# [6] 1.359676e+09 6.154045e+03 1.777027e+01 1.070003e+04 6.217397e+04
sum(exp(x/t))
# [1] 2984044296

由于分子是长度为10的向量,分母是长度为1的向量,因此除法返回长度为10的向量。

由于你有兴趣将它与Python进行比较,想象一下将以下两条规则添加到Python中(顺便说一句,这些规则类似于numpy中数组的用法):

  1. 如果您将列表除以数字,它会将列表中的所有项目除以数字:

    [2, 4, 6, 8] / 2
    # [1, 2, 3, 4]
    
  2. Python中的函数exp是“矢量化的”,这意味着当它应用于列表时,它将应用于列表中的每个项目。但是,总和仍然按照您的预期方式运作。

    exp([1, 2, 3]) => [exp(1), exp(2), exp(3)]
    
  3. 在这种情况下,想象一下如何在Python中评估此代码:

    t = .1
    x = [1, 2, 3, 4]
    exp(x/t) / sum(exp(x/t))
    

    使用这两个简单的规则将遵循以下简化:

    exp([v / t for v in x]) / sum(exp([v / t for v in x]))
    [exp(v / t) for v in x] / sum([exp(v / t) for v in x])
    

    现在你知道它是如何知道差异的吗?

答案 2 :(得分:1)

向量化在R中有几个略微不同的含义。

这可能意味着接受矢量输入,转换每个元素,并返回一个矢量(如exp那样)。

它还可以表示接受向量输入并计算一些摘要统计量,然后返回标量值(如mean那样)。

sum符合第二种行为,但也有第三种向量化行为,它会在输入中创建一个摘要统计量。例如,尝试sum(1, 2:3, 4:6)