【问题标题】:Passing data.frame as an argument in function将 data.frame 作为参数传递给函数
【发布时间】:2017-04-19 14:50:14
【问题描述】:

上下文

作为R: Pass data.frame by reference to a functionHow to add a column in the data frame within a function 的后续行动

我正在尝试以下看似简单的功能:

naToZero <- function(df) {
  df$Vol[is.na(df$Vol)] <- 0
}

数据帧

> str(WFM)
Classes ‘tbl_df’, ‘tbl’ and 'data.frame':   990571 obs. of  14 variables:
 $ Date      : chr  "04/12/2017" "04/12/2017" "04/12/2017" "04/12/2017" ...
 $ Time      :Classes 'hms', 'difftime'  atomic [1:990571] 41970 41969 41968 41967 41966 ...
  .. ..- attr(*, "units")= chr "secs"
 $ Bar#      : chr  "197953/197953" NA "197952/197953" NA ...
 $ Bar Index : int  0 NA -1 NA NA -2 NA NA -3 NA ...
 $ Tick Range: int  0 NA 0 NA NA 0 NA NA 0 NA ...
 $ Open      : num  33.9 NA 33.9 NA NA ...
 $ High      : num  33.9 NA 33.9 NA NA ...
 $ Low       : num  33.9 NA 33.9 NA NA ...
 $ Close     : num  33.9 NA 33.9 NA NA ...
 $ Vol       : int  100 NA 200 NA NA 100 NA NA 400 NA ...
 $ MACDHist  : num  -59 NA -87 NA NA ...
 $ MACD      : num  -450 NA -445 NA NA ...
 $ MACDSig   : num  -391 NA -358 NA NA ...
 $ ZScore1   : num  NA NA NA NA NA NA NA NA NA NA ...

希望使用这个功能来加快数据清理的速度。

问题

在我在脚本编辑器中运行该函数后,然后传递一个 data.frame 来运行它。但是该功能没有做任何事情,当我查看(WFM)时,它仍然是相同的旧数据。但是,当我手动运行命令时:

WFM$Vol[is.na(WFM$Vol)] &lt;- 0

然后就可以了。

我尝试过的事情

我尝试根据我看到的两个链接进行实验,似乎相关:

使用WFM &lt;- naToZero(WFM),产生一个具有单个值的向量,0。

尝试使用WFM &lt;- data.table(WFM) 并运行该函数...同样的事情。

我一定错过了一些基本的东西。

【问题讨论】:

    标签: r function


    【解决方案1】:

    实际上,R 中的所有对象都是不可变的:操作不会修改原始对象,它们会创建副本。因此,您需要将该副本分配回原件

    &lt;- 会这样做,但它会分配给 df在您的函数中,这是您传递给的参数 (= WFM) 的副本你的功能。

    所以你需要修改你的函数:

    naToZero <- function(df) {
        df$Vol[is.na(df$Vol)] <- 0
        df
    }
    

    ……以及您如何称呼它:

    WFM = naToZero(WFM)
    

    【讨论】:

    • 有趣的机制,澄清我的理解:通过将df 添加到函数中,我们本质上是“将副本带到前面”,从而使其足够明确以将其分配回原始通过WFM = naToZero(WFM)?
    • @RobertTan 不,它只是确保函数调用的返回值为df。否则函数调用的返回值就是赋值的值(&lt;- 0),也就是赋值本身,即0(如你所见)。
    【解决方案2】:

    我们可以使用dplyr 的开发版(即将发布0.6.0)使其更具动态性

    library(tidyverse)
    naToZero <- function(df, Col) {
        Col <- enquo(Col)
        ColN <- quo_name(Col)
         df %>% 
          mutate(!!ColN := replace(!!Col, is.na(!!Col), 0))
     
    
    }
    
    naToZero(WFM, Vol)
    # A tibble: 3 × 2
    #       Date   Vol
    #      <chr> <dbl>
    #1 04/12/2017     0
    #2 04/12/2017    23
    #3 04/12/2017    40
    

    或任何其他列

    naToZero(WFM, Open)
    # A tibble: 3 × 3
    #       Date   Vol  Open
    #       <chr> <dbl> <dbl>
    #1 04/12/2017    NA  33.9
    #2 04/12/2017    23   0.0
    #3 04/12/2017    40  32.0
    

    enquobase R 中的substitute 具有相似的功能,方法是获取输入参数并将其转换为quosure。在mutate 中,我们可以取消引用(!!UQ)来评估列以及使用quo_name 创建的 lhs 上的字符串

    数据

    WFM <- tibble(Date = rep("04/12/2017", 3), Vol = c(NA, 23, 40), Open = c(33.9, NA, 32))
    

    【讨论】:

    • 我不确定这是否对 OP 有帮助……同样可以使用 base R 实现(使用更少的代码!)。(虽然我个人是 dplyr 版本的粉丝,但不用说.)
    • @KonradRudolph 是的,可以做到,但是查看 OP 的数据集,它来自 tbl_df
    猜你喜欢
    • 2013-01-27
    • 2023-02-05
    • 2015-03-17
    • 2021-04-13
    • 1970-01-01
    • 2021-01-02
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多