【问题标题】:Plotting in R using Java - works, but cannot find the plot使用 Java 在 R 中绘图 - 有效,但找不到绘图
【发布时间】:2013-09-02 13:51:37
【问题描述】:

我正在尝试从 Java 中调用一些 r 代码,就像这样:

private void makeMatrix() throws ScriptException {
    try {
        Runtime.getRuntime().exec(" Rscript firstscript.r");
        System.out.println("Script executed");
         } catch (IOException ex) {
       System.out.println("Exception");
       System.out.println(ex.getMessage());
    }

}

好吧,我得到了“执行脚本”的打印。

我的(好吧,不是我的,只是为了测试)r-Code 相当简单,几乎只是为了看看它是否有效:

x=seq(0,2,by=0.01)
y=2*sin(2*pi*(x-1/4))
plot(x,y)

所以,它不应该做的只是画一个鼻窦。

但是,不应该有某种弹出窗口可以让您实际看到情节吗? 因为没有。我做错了什么?

编辑:为了响应我来到这里的 cmets,我编辑了 r 文件,添加:

jpeg('rplot.jpg')
plot(x,y)
dev.off()

到它。

但是,如果我尝试在我的系统上找到 rplot.jpg,它根本不存在。

【问题讨论】:

  • 你应该明确地为情节声明一个新设备。在 OSX 上,函数是 quartz,在 Windows 上是 windows,在 *nix 上我相信你想要 X11。使用例如png 将绘图保存到文件中然后从 Java 打开文件可能更有意义。
  • 您可能还想看看rJavaRcaller,后者具有显式绘图支持而不是手动调用R 可执行文件。
  • 我看了他们两个。问题是,jar 必须在 windows 和 linux 上是可执行的,而我根本没有管理它。
  • 阅读(并实施)所有 When Runtime.exec() won't 的建议。那可能会解决问题。如果不是,它应该提供更多关于失败原因的信息。然后忽略它引用exec 并使用ProcessBuilder 构建Process。还要将String arg 拆分为String[] args 以说明本身包含空格的参数。
  • 如果我收到错误消息或异常,我会很高兴,但我怎么能得到我的打印但我在 rscript 中制作的文件不在我的系统上?

标签: java r runtime.exec


【解决方案1】:

您将相对目录传递给 jpeg 函数。这使它相对于 R 的当前工作目录(getwd 返回的值)。

尝试打印此值以查看其位置(在 Windows 上,默认情况下它位于当前用户的“我的文档”中)

print(getwd())

或将绝对路径传递给jpeg

jpeg('c:/rplot.jpg')
plot(x,y)
dev.off()

要获取绝对路径,请使用pathological::standardize_pathR.utils::getAbsolutePath

【讨论】:

  • 这似乎是问题所在。但是,我如何找到这个绝对路径(无需再次使用 runtime.exec)?我想根据用户用来打开 jar 的计算机,脚本(捆绑在 jar 中)也会在另一个文件夹中,不是吗?
  • 我有一个奇怪的想法....实际上,只要用户启动程序,我就可以在用户计算机上创建那些 r 脚本。我想这会奏效,但这种解决方案是否明智?
【解决方案2】:

您可以等待Processexec 返回一个Process 对象)完成 与waitFor,并检查退出值:它应该是0。

如果不为零,则可能需要指定脚本的路径。

public static void main( String[] args ) throws IOException, InterruptedException {
    Process p = Runtime.getRuntime().exec("Rscript /tmp/test.R");
    System.out.println("Started");
    p.waitFor();
    if( p.exitValue() != 0 )
        System.out.println("Something went wrong");
    else 
        System.out.println("Finished");
}

如果退出值不为0,可以查看进程的stdout和stderr, 正如 Andrew 的评论中所建议的那样。

public static void main(String[] args) throws IOException, InterruptedException {
    System.out.println("test...");
    Process p = Runtime.getRuntime().exec(new String[] {
        "Rscript",
        "-e",
        "print(rnorm(5)))" // Intentional error, to produce an error message
    } );
    System.out.println("Started");

    String line = null;

    System.out.println("Stdout:");
    BufferedReader stdout = new BufferedReader( new InputStreamReader( p.getInputStream() ) );
    while ( (line = stdout.readLine()) != null)
        System.out.println(line);

    System.out.println("Stderr:");
    BufferedReader stderr = new BufferedReader( new InputStreamReader( p.getErrorStream() ) );
    while ( (line = stderr.readLine()) != null)
        System.out.println(line);

    p.waitFor();
    if( p.exitValue() != 0 )
        System.out.println("Something went wrong, exit value=" + p.exitValue());
    else 
        System.out.println("Finished");
}

正如 cmets 中提到的, 您需要显式打开设备。 由于脚本终止时关闭,所以还需要添加延迟。

x11() # Open a device (also works on Windows)
plot( rnorm(10) )
Sys.sleep(10) # Wait 10 seconds

【讨论】:

  • device是指图形输出的类型,例如窗口、PNG文件、PDF文件等。x11()windows()是等价的,打开一个窗口显示情节。检查?device
  • 有时我可以......我知道我的 r-skript 没有错误,因为通过命令行使用完全相同的脚本。我知道绝对路径是正确的,我仍然开始/错误。有人知道吗?
  • 听从 Andrew 的建议,在上面的 cmets 中,打印过程的标准输出和标准错误:你就会知道哪里出了问题。我已经相应地更新了我的答案。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-09-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多