(这是什么巫术?

在回答另一个问题时,@Marek发布了以下解决方案:https://stackoverflow.com/a/10432263/636656

dat <- structure(list(product = c(11L, 11L, 9L, 9L, 6L, 1L, 11L, 5L, 
                                  7L, 11L, 5L, 11L, 4L, 3L, 10L, 7L, 10L, 5L, 9L, 8L)), .Names = "product", row.names = c(NA, -20L), class = "data.frame")

`levels<-`(
  factor(dat$product),
  list(Tylenol=1:3, Advil=4:6, Bayer=7:9, Generic=10:12)
  )

作为输出产生:

 [1] Generic Generic Bayer   Bayer   Advil   Tylenol Generic Advil   Bayer   Generic Advil   Generic Advil   Tylenol
[15] Generic Bayer   Generic Advil   Bayer   Bayer  

这只是一个矢量的打印输出,所以要存储它,你可以做更多的混淆:

res <- `levels<-`(
  factor(dat$product),
  list(Tylenol=1:3, Advil=4:6, Bayer=7:9, Generic=10:12)
  )

很明显,这是对关卡功能的某种调用,但我不知道这里正在做什么。 这种巫术的术语是什么,如何提高我在这个领域的魔法能力?


这里的答案很好,但他们缺少重要的一点。 让我试着描述它。

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<- 。 我承认名称levels<-有点令人困惑,因为它表明了一项任务,但这不是发生了什么。 代码只是设置了一种管道:

  • dat$product开始

  • 将其转换为一个因子

  • 更改级别

  • 将其存储在res

  • 就我个人而言,我认为这行代码很漂亮;)


    这个“魔术”的原因是,“分配”形式必须有一个真正的变量来处理。 而这个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)
      )
    

    没有巫术,只是如何定义(子)赋值函数。 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! ;-)
    
    链接地址: http://www.djcxy.com/p/24887.html

    上一篇: `( What sorcery is this?

    下一篇: How to make good reproducible pandas examples