【问题标题】:Call R from JAVA to get Chi-squared statistic and p-value从 JAVA 调用 R 以获取卡方统计量和 p 值
【发布时间】:2013-04-07 19:57:23
【问题描述】:

我在 JAVA 中有两个 4*4 矩阵,其中一个矩阵保存观察到的计数,另一个保存预期计数。

我需要一种自动方法来计算这两个矩阵之间的卡方统计量的 p 值;但是,据我所知,JAVA 没有这样的功能。

我可以通过将两个矩阵作为 .csv 文件格式读取到 R 中,然后使用 chisq.test 函数来计算卡方及其 p 值,如下所示:

obs<-read.csv("obs.csv")
exp<-read.csv("exp.csv")
chisq.test(obs,exp)

.csv 文件的格式如下:

A, C, G, T
A, 197.136, 124.32, 63.492, 59.052
C, 124.32, 78.4, 40.04, 37.24
G, 63.492, 40.04, 20.449, 19.019
T, 59.052, 37.24, 19.019, 17.689

给定这些命令,R 将给出以下格式的输出:

X-squared = 20.6236, df = 9, p-value = 0.01443

其中包括我正在寻找的 p 值。

有谁知道自动化流程的有效方法:

1) 将我的矩阵从 JAVA 输出到 .csv 文件 2) 将 .csv 文件上传到 R 3) 将 .csv 文件上的 chisq.test 调用到 R 中 4) 将输出的 p 值返回到 JAVA 中?

感谢您的帮助....

【问题讨论】:

  • 感谢您的链接。我正在将此代码提交给老师。这种方法是否意味着她需要将一些东西下载到她的计算机上才能运行我的代码。如果是这样,是否有替代方案不会强制这样做?再次感谢!!

标签: java r statistics chi-squared


【解决方案1】:

查看此页面JRI

他们网站的描述:

JRI 是一个 Java/R 接口,它允许在 Java 中运行 R 应用程序作为单线程。基本上它加载 R 动态库 进入 Java 并为 R 功能提供 Java API。它同时支持 对 R 函数的简单调用和完整运行的 REPL。

【讨论】:

  • 感谢您的链接。我正在将此代码提交给老师。这种方法是否意味着她需要将一些东西下载到她的计算机上才能运行我的代码。如果是这样,是否有替代方案不会强制这样做?再次感谢!!
【解决方案2】:

有(至少)两种方法可以解决这个问题。


命令行和脚本

您可以使用Rscript.exe 从命令行执行 Rscripts。例如。在您的脚本中,您将拥有:

# Parse arguments.
# ...
# ...

chisq.test(obs, exp)

您应该能够将它们直接传递给 R,而不是在 Java 中创建 CSV 并让 R 读取它们。我认为不需要创建 CSV 并以这种方式传递数据,除非您的矩阵非常大。您可以传递的命令行参数的大小有限制(我认为因操作系统而异)。

您可以将参数传递到 Rscripts 并使用 commandArgs() 函数或各种包(例如 optparsegetopt)解析它们。见this thread for more information

在 Java 中有几种从命令行调用和读取的方法。我对它的了解不够多,无法给你建议,但谷歌搜索一下会给你一个结果。从命令行调用脚本是这样完成的:

Rscript my_script.R

JRI

JRI 让您可以直接从 Java 与 R 对话。这是一个示例,说明如何将双精度数组传递给 R 并让 R 对其求和(现在是 Java):

// Start R session.
Rengine re = new Rengine (new String [] {"--vanilla"}, false, null);

// Check if the session is working.
if (!re.waitForR()) {
    return;
}

re.assign("x", new double[] {1.5, 2.5, 3.5});
REXP result = re.eval("(sum(x))");
System.out.println(result.asDouble());
re.end();

这里的函数assign()和R里做的一样:

x <- c(1.5, 2.5, 3.5)

您应该能够弄清楚如何扩展它以使用矩阵。


我认为 JRI 一开始是相当困难的。因此,如果您想快速完成此操作,命令行选项可能是最好的。我会说 JRI 方法一旦设置好就不会那么混乱了。而且,如果您遇到在 R 和 Java 之间来回频繁的情况,那肯定比调用多个脚本要好。

  1. Link to JRI
  2. Recommended Eclipse plugin to set up JRI

【讨论】:

  • 我得到错误:import org.rosuda.JRI.REXP 无法解析,import org.rosuda.JRI.Rengine 无法解析,Rengine 无法解析为一个类型。关于可能导致这种情况的任何想法?再次感谢...
  • 我看到您已经对此提出了另一个问题。如果您仍然无法设置它,我建议您使用我在回答中建议的插件(最后一个链接)。它解决了设置 JRI 的所有压力,这可能非常困难。
【解决方案3】:

1) 将我的矩阵从 JAVA 输出到 .csv 文件中

使用任何 CSV 库,我会推荐 http://opencsv.sourceforge.net/

2) 将 .csv 文件上传到 R 3)将.csv文件上的chisq.test调用到R中

2 & 3 差不多, 您最好创建要在 R 中运行的参数化脚本。

obs<-read.csv(args[1])
exp<-read.csv(args[2])
chisq.test(obs,exp)

这样你就可以运行了

RScript your_script.r path_to_csv1 path_to_csv2, 

并为 csv 文件使用唯一名称,例如:

UUID.randomUUID().toString().replace("-","")

然后你使用

Runtime.getRuntime().exec(command, environments, dataDir);

4) 将输出的 p 值返回到 JAVA? 如果您使用 getRuntime().exec() 调用 R,则只能读取 R 的输出。

我还建议您查看Apache's Statistics LibHow to calculate PValue from ChiSquare。也许你可以完全没有 R :)

【讨论】:

    【解决方案4】:

    我建议简单地使用为您进行 ChiSquare 测试的 Java 库。它们已经足够了:

    这不是一个完整的列表,而是我在 5 分钟的搜索中找到的。

    【讨论】:

      【解决方案5】:

      RCaller 2.2 可以做你想做的事。假设在您的问题中给出了频率矩阵。生成的 p.value 和 df 变量可以使用以下代码计算并返回:

      double[][] data = new double[][]{
              {197.136, 124.32, 63.492, 59.052},
              {124.32, 78.4, 40.04, 37.24},
              {63.492, 40.04, 20.449, 19.019},
              {59.052, 37.24, 19.019, 17.689}
              };
          RCaller caller = new RCaller();
          Globals.detect_current_rscript();
          caller.setRscriptExecutable(Globals.Rscript_current);
          RCode code = new RCode();
      
          code.addDoubleMatrix("mydata", data);
          code.addRCode("result <- chisq.test(mydata)");
          code.addRCode("mylist <- list(pval = result$p.value, df=result$parameter)");
      
          caller.setRCode(code);
          caller.runAndReturnResult("mylist");
      
          double pvalue = caller.getParser().getAsDoubleArray("pval")[0];
          double df = caller.getParser().getAsDoubleArray("df")[0];
          System.out.println("Pvalue is : "+pvalue);
          System.out.println("Df is : "+df);
      

      输出是:

      Pvalue is : 1.0
      Df is : 9.0
      

      您可以在here获取技术详情

      【讨论】:

        【解决方案6】:

        Rserve 是另一种将数据从 Java 获取到 R 并返回的方法。它是一个将 R 脚本作为字符串输入的服务器。您可以使用Java中的一些字符串解析和转换将矩阵转换为可以输入到R中的字符串。

        import org.rosuda.REngine.REXP;
        import org.rosuda.REngine.Rserve.RConnection;
        
        
        public class RtestScript {
        
        private String emailTestScript = "open <- c('O', 'O', 'N', 'N', 'O', 'O', 'N', 'N', 'N', 'O', " +
                " 'O', 'N', 'N', 'O', 'O', 'N', 'N', 'N', 'O');" +
                "testgroup <- c('A', 'A', 'A','A','A','A','A','A','A','A', 'B'," +
                "'B', 'B', 'B', 'B', 'B', 'B', 'B', 'B');" +
                "emailTest <- data.frame(open, testgroup);" +
                "emailTable<- table(emailTest$open, emailTest$testgroup);" +
                "emailResults<- prop.test(emailTable, correct=FALSE);" +
                "print(emailResults$p.value);";
        
        public void executeRscript() {
            try {
                //Make sure to type in library(Rserve); Rserve() in Rstudio before running this
                RConnection testConnection = new RConnection();
        
                REXP testExpression = testConnection.eval(emailTestScript);
                System.out.println("P value: " + testExpression.asString());
            } catch(Exception e) {
                e.printStackTrace();
            }
        }
        }
        

        这里是有关 Rserve 的更多信息。顺便说一句,这也是 Tableau 与 R 以及它们的 R 连接进行通信的方式。

        https://cran.r-project.org/web/packages/Rserve/index.html

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2022-11-19
          • 2021-10-02
          • 1970-01-01
          • 2014-06-30
          • 2015-12-20
          • 2021-11-26
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多