3 回答
TA贡献1833条经验 获得超4个赞
这里的答案是好的,但是它们缺少重要的一点。让我尝试描述一下。
R是一种功能语言,不喜欢对其对象进行突变。但是它确实允许使用替换函数进行赋值语句:
levels(x) <- y
相当于
x <- `levels<-`(x, y)
诀窍是,这种重写是由<-; 完成的。它不是由levels<-。levels<-只是一个接受输入并给出输出的常规函数;它不会改变任何东西。
结果之一是,根据上述规则,<-必须是递归的:
levels(factor(x)) <- y
是
factor(x) <- `levels<-`(factor(x), y)
是
x <- `factor<-`(x, `levels<-`(factor(x), y))
这种纯功能的转换(直到最后,发生赋值)等同于一种命令式语言中的赋值,这是一种美丽。如果我没记错的话,这种用功能语言构造的镜头称为镜头。
但是,一旦您定义了诸如的替换函数levels<-,您将获得另一个意想不到的意外收获:您不仅具有进行分配的能力,还拥有一个方便的函数,该函数吸收了一个因数,并给出了另一个具有不同级别的因数。确实没有任何“分配”!
因此,您所描述的代码只是利用的另一种解释levels<-。我承认这个名称levels<-有点令人困惑,因为它暗示了一项任务,但是事实并非如此。该代码只是建立了一种管道:
从...开始 dat$product
将其转换为因子
改变水平
存放在 res
我个人认为代码行很漂亮;)
TA贡献1802条经验 获得超4个赞
没有法宝,这就是(子)分配功能的定义方式。 levels<-有所不同,因为它是(子)分配因子属性而不是元素本身的原始函数。有很多此类函数的示例:
`<-` # assignment
`[<-` # sub-assignment
`[<-.data.frame` # sub-assignment data.frame method
`dimnames<-` # change dimname attribute
`attributes<-` # change any attributes
其他二进制运算符也可以这样调用:
`+`(1,2) # 3
`-`(1,2) # -1
`*`(1,2) # 2
`/`(1,2) # 0.5
既然您知道了,类似这样的事情应该真的让您大吃一惊:
Data <- data.frame(x=1:10, y=10:1)
names(Data)[1] <- "HI" # How does that work?!? Magic! ;-)
TA贡献1842条经验 获得超12个赞
之所以说是“魔术”,是因为“赋值”表格必须具有实际变量才能使用。而且factor(dat$product)没有分配任何东西。
# This works since its done in several steps
x <- factor(dat$product)
levels(x) <- list(Tylenol=1:3, Advil=4:6, Bayer=7:9, Generic=10:12)
x
# This doesn't work although it's the "same" thing:
levels(factor(dat$product)) <- list(Tylenol=1:3, Advil=4:6, Bayer=7:9, Generic=10:12)
# Error: could not find function "factor<-"
# and this is the magic work-around that does work
`levels<-`(
factor(dat$product),
list(Tylenol=1:3, Advil=4:6, Bayer=7:9, Generic=10:12)
)
- 3 回答
- 0 关注
- 831 浏览
添加回答
举报