从JAVA调用R获取卡方统计量和p值

3

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

我需要一种自动化的方法来计算这两个矩阵之间卡方统计量的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)在R中对.csv文件调用chisq.test 4)将输出的p值返回到JAVA?

感谢任何帮助...


谢谢提供链接。我将把这段代码提交给老师。这种方法是否意味着她需要下载一些东西到她的电脑上才能运行我的代码?如果是这样,有没有其他的选择不需要强制下载呢?再次感谢! - user1830307
6个回答

12

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


命令行和脚本

你可以使用Rscript.exe从命令行执行R脚本。例如,在你的脚本中,你可以有:

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

chisq.test(obs, exp)
与其在Java中创建CSV并让R读取,你应该能够直接将它们传递给R。除非矩阵非常大,否则我不认为需要创建CSV并通过这种方式传递数据。您可以使用commandArgs()函数或各种软件包(例如optparsegetopt)将参数传递到R脚本并解析它们。有关更多信息,请参见此主题
在Java中,有几种从命令行调用和读取的方法。我了解不足,无法给出建议,但通过一些搜索您将能找到结果。从命令行调用脚本的方法如下:
Rscript my_script.R

JRI

JRI允许您直接从Java与R交互。以下是一个示例,演示如何将一个double数组传递给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. JRI链接
  2. 推荐的Eclipse插件以设置JRI

我遇到了以下错误:import org.rosuda.JRI.REXP无法解析,import org.rosuda.JRI.Rengine无法解析,Rengine无法解析为类型。您有什么想法是什么原因导致的吗?再次感谢... - user1830307
我看到你已经开了另一个关于这个问题的问题。如果你仍然在设置上遇到麻烦,我建议使用我在答案中提到的那个插件(最后一个链接)。它会处理所有设置JRI的压力,这可能会让人惊讶地困难。 - Ciarán Tobin

2

请查看这个页面JRI

他们网站上的描述:

JRI是一个Java/R接口,允许将R作为单线程在Java应用程序中运行。它基本上将R动态库加载到Java中并提供了一个Java API来实现R功能。它支持对R函数的简单调用以及完整的运行REPL。


谢谢提供链接。我将把这段代码提交给老师。这种方法是否意味着她需要下载一些东西到她的电脑上才能运行我的代码?如果是这样,有没有其他的选择不需要强制下载呢?再次感谢! - user1830307

1

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进行通信的方式。

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


1

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

你可以在这里获取技术细节。

0

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

使用任何CSV库,我建议http://opencsv.sourceforge.net/

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

第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的统计库如何从卡方计算PValue。也许您完全可以不使用R :)


0

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接