为什么R代码在本地运行,而不在Docker中运行?

时间:2020-01-28 17:55:34

标签: r docker amazon-s3

我有一个Docker容器,该容器设置为每周通过Airflow DAG运行R脚本。 DAG具有3个事件-1在Docker代码的上游,该Docker代码从多个数据库获取数据,计算各种功能,然后将数据写入S3。该脚本从S3存储桶中读取数据,格式化数据帧,运行模型以对记录进行评分,然后将数据写回到S3。最后,还有下游代码可以格式化输出,以便可以将其加载到Salesforce中。当我在12月编写并构建该脚本时,该脚本在测试时有效。最近,运行失败了几次,错误代码为:


    Error in as.character(x) : 
      cannot coerce type 'closure' to vector of type 'character'
    Calls: %>% ... mutate_impl -> ymd -> .parse_xxx -> unlist -> lapply -> FUN
    Execution halted

好的,这似乎意味着它作为字符读入的日期存在格式被格式化为日期的问题。由于'ymd'在链中,因此我相信它是下面R脚本中的Lubridate函数。

Docker文件(以下代码)利用具有Tidyverse的R映像,因为我的代码使用Dplyr和Lubridate。如果没有Lubridate,我可能会过得去,并使用基本函数来格式化日期,但下面对此进行了详细介绍

Docker文件代码:


    FROM rocker/tidyverse

    RUN mkdir -p /model

    RUN apt-get update -qq && apt-get install -y \
          libssl-dev \
          libcurl4-gnutls-dev 

    RUN R -e "install.packages('caret')"

    RUN R -e "install.packages('randomForest')"

    RUN R -e "install.packages('lubridate')"

    RUN R -e "install.packages('aws.s3')"

    EXPOSE 80

    EXPOSE 8787

    COPY / /

    ENTRYPOINT ["Rscript", "account_health_scoring.R"]

R脚本:由于某些识别信息和凭据,我不得不排除前几行,但是代码首先只是从文件中读取了我的S3凭据。然后,此代码块运行并失败。下游有很多代码,但是所有这些功能都在容器中:

require("dplyr")
require("caret")
require("aws.s3")
require("randomForest")
require("lubridate")

#set credentials
Sys.setenv("AWS_ACCESS_KEY_ID" = "key",
           "AWS_SECRET_ACCESS_KEY" = "key")

#read in model file
s3load("rf_gridsearch.RData", bucket = "account-model")


#read in data
    data<-read.csv(text = rawToChar(get_object((paste0("account_health_data_",
                                                       gsub("-", "_", as.character(Sys.Date()),
                                                            fixed=TRUE),".csv")),
                                               bucket = "account-health-model-input")),
      stringsAsFactors = FALSE)%>%
      mutate(period=ymd(period))%>%
      mutate_if(is.integer,as.numeric)

2条突变行的原因是,尽管R被格式化为POSIX时间戳,但R将日期强制转换为字符串,并且将强制浮动为整数。也许我的read.csv文件中也缺少此内容,或者有一个更好的功能可以正确读取数据,但这就是我一直使用的功能。

问题:

  1. 关于/ am的错误消息是什么?我正确地认为YMD函数是罪魁祸首?

  2. 如果是这样,我该如何潜在地使用基本函数来重写我的代码以实现相同的目标并避免依赖于包。

  3. 可能是程序包依赖性吗?在查看日志时,似乎不是这种情况,因为Lubridate会导入多个基本函数/使用多个基本函数。自从我编写并测试了这段代码以来,该软件包尚未更新。

1 个答案:

答案 0 :(得分:0)

嗯,尽管我不理解,答案似乎很简单。我改变了


    require(lubridate)


    library(lubridate)

它建立了。我找到了这篇帖子What is the difference between require() and library()?,并决定只是尝试对其进行更改,构建了容器,然后它起作用了。我仍在尝试理解“为什么”。