java调用r语言 实现聚类分析结果返回

来源:互联网 发布:mac mini 安装win7 编辑:程序博客网 时间:2024/05/18 13:26

因项目要求,需要将数据进行聚类分析。r语言正合适进行数据处理,于是开始了0经验的摸索使用的经历,留个记录(工作经历尚浅,如有错误处,欢迎指出,我好好进行学习)

之前都是C#进行开发。此次项目要求 需要前段html,后端Java。因此采用前段使用html,后端是用Java写servlet进行数据的返回。(前端发送http请求servlet,servlet接收到参数,进行相应的操作,返回聚类后的数据)。

以下记录完成聚类以及数据获取的流程,以及过程中所遇到的问题:

1.Java新建一个servlet,http请求后,执行doget()函数,里面获取参数,调用相应函数。

2.Java调用R语言。网络搜索一番,发现有rjava,与rserve,等方式。我采用的rserve的方式(好处是支持远程调用)。首先下载个R语言的安装包然后安装。

安装完成后,要使用的r语言的各种分析的方法前,都应先安装具体的包。直接在命令行出输入命令。安装命令如(install.packages("Rserve"))安装时选择一个地区的镜像,等待下载安装即可,其次使用具体函数前都应先加载library相应的包(library(mic)聚类相关的函数的包)。(r相关的变成,函数这块,是有以为研究生帅哥完成的。我只是负责将Java调用r弄通。也感谢研究生帅哥的对我这个菜鸟的耐心指导)。在r软件内打开reserve.exe服务后,通过Java使用代码段,就测试实现了调用成功。

try {

RConnection c = new RConnection("127.0.0.1");

String x = c.eval("R.version.string").asString();

System.out.println(x);
response.getWriter().write(x);

} catch (Exception e) {

e.printStackTrace();

}
。控制台如果能够看到r软件的版本号,说明测试通过。

3.数据前期准备:servlet能够成功调用r语言之后,就是给r语言传输具体的数据了,r语言应该是能够解析多种格式的数据的。由于能力所致,较熟悉json格式的,因此照着在r软件中实验过得基础json格式进行构造了项目所需的json字符串,并写入到本地的.json文件中。其格式为:

{
   "ID":["1","2","3","4","5","6","7","8" ],
   "Name":["Rick","Dan","Michelle","Ryan","Gary","Nina","Simon","Guru" ],
   "Salary":["623.3","515.2","611","729","843.25","578","632.8","722.5" ],
   "StartDate":[ "1/1/2012","9/23/2013","11/15/2014","5/11/2014","3/27/2015","5/21/2013","7/30/2013","6/17/2014"],
   "Dept":[ "IT","Operations","IT","HR","Finance","IT","Operations","Finance"]
}。(感觉r语言主要的工作是进行数据的聚类统计分析,主要的前期数据处理也是非常重要的,前期的数据准确度越高,r处理后的数据也就越接近于现实。)数据处理流程如图

4.获取数据,前段使用jQuery获取经过r处理后的json数据。再在客户端转换为对象,即可使用。

5.所遇到的问题。因为之前没有接触过,所以遇到的问题可能比较弱智吧。快哭了

5.1:servlet调用r语言的测试完成后,如何完成具体的r处理的n多条命令,命令在哪里输入?如果r里面的处理是有for循环的,怎么写在servlet里面。

   解决:首先,只要测试通过了,那么肯定是能够调用的,此处也是卡了挺久,一度想换成rjava试一试。命令其实就是写在String x = c.eval("R.version.string").asString();的引号中。只试过一行一句,也有可能可以批量。暂时没尝试。

如果是for循环,构造成一个字符串去执行时不行的。就要像正常函数一样,该换行换行,写的时候,换行是加个\n读取即可。


RConnection c = new RConnection();
try{
c.eval("library(rjson)");
c.eval("library(mice)");
c.eval("library(Rcpp)");
c.eval("library(reshape)");

c.eval("jsdata<-fromJSON(file=\"C:/temp_m/param_hspf.json\",unexpected.escape=\"error\")");
c.eval("data01<-as.data.frame(jsdata,head=T)");
c.eval("data02<-apply(data01[,2:9],2,as.numeric)");
c.eval("data<-cbind(data01[,c(1,10)],data02)");
c.eval("data[data==0]<-NA");

c.eval("cdata<-mice(data[,3:10],num=3,seed=01)");
c.eval("mc_data<-complete(cdata,2)");
c.eval("mdata<-cbind(data[,1:2],mc_data)");
c.eval("midata<-aggregate(mdata[,3:10],list(mdata[,1]),mean)");
c.eval("medate<-round(midata[,2:9],3)");
c.eval("medata<-cbind(midata[,1],medate)");
c.eval("colnames(medata)[1]<-\"STATION_CODE\"");
c.eval("scaldata<-scale(medata[,2:9],center=T,scale=F)");

c.eval("CREATETIME<-mdata$CREATETIME[1]");
c.eval("result<-cbind(medata,CREATETIME)");
c.eval("for(i in 1:8){\n dist.e<-dist(scaldata[,i],method='euclidean')\n model1=hclust(dist.e,method='ward.D')\n for(j in 3:6){\n cname1<-cutree(model1,k=j)\n cname2<-paste(colnames(scaldata)[i],\"class\",j,sep=\"_\")\n result=cbind(result,cname1)\n result<-rename(result,c(cname1=cname2))}}");
c.eval("dist.e_v<-dist(scaldata,method='euclidean')");
c.eval("model2=hclust(dist.e,method='ward.D')");
c.eval("result03=cutree(model2,k=3)");
c.eval("result04=cutree(model2,k=4)");
c.eval("result05=cutree(model2,k=5)");
c.eval("result06=cutree(model2,k=6)");
c.eval("result<-cbind(result,result03,result04,result05,result06)");

String resultJson= c.eval("Tojsdata<-toJSON(result,method=\"C\")").asString();
c.close();

使用完成后,不管成功与否,代码中最好都得第一时间关闭连接。c.close();!!!开始因为没有关闭,然后加上r语言的命令也有些问题,导致一般就出错了。重新启动后,继续运行,会一直开着开启连接那里。开始还以为是连接不上了,其实就是因为没有关闭连接造成的。

5.2:如何通过servlet开始Rserve服务。

      Java实现开启后台的代码有很多,但是我遇到的问题是,rserve只能通过r软件进行输入命令library(Rserve),Rserve();  我找到本地的rserve文件,双击会报错。说找不到r.dll。解决方式是把rserve.exe文件拷到有r.dll的目录地下,*386 和*64位的都拷贝过去。记得是拷到bin目录下。(通过该网址解决的这个问题https://wenku.baidu.com/view/06014436e45c3b3567ec8bee.html)这样,双击便可以打开rserve.exe文件了。也就可以通过Java的servlet开启相应的rserve服务,而不需要通过手动开启服务了。以下是开启服务的代码: RunModle("C:\\R\\R-3.1.3\\bin\\x64","Rserve.exe");
public void RunModle(final String FilePath,final String FileName){
//String path = "C:\\Users\\Administrator\\Desktop\\weixinPC_2.4.1.79.exe";
new Thread(){
public void run() {
try {
//String cmdStr1 = "cmd /c c: cd "+FilePath+" && del wasp1.dat && del wasp2.dat && del wasp3.dat && del wasp4.dat && del wasp5.dat " ;//先删除相关输出文件process.txt
String cmdStr1="cmd /c c: && del c:\\temp_m\\wasp1.dat && del c:\\temp_m\\wasp2.dat && del c:\\temp_m\\wasp3.dat && del c:\\temp_m\\wasp4.dat && del c:\\temp_m\\wasp5.dat && del c:\\temp_m\\process.txt";
Runtime.getRuntime().exec(cmdStr1);
String cmdStr = "cmd /c c: && cd "+FilePath+" && "+FileName ;//&&
Runtime.getRuntime().exec(cmdStr);
System.out.println(cmdStr);
} catch (IOException e) {
e.printStackTrace();
System.out.println("no");
}
}
}.start();

}。 

5.3:关闭rserve.exe遇到的问题。

java关于通过进程名称关闭进程的教程有很多。 通过搜索找到了许多,应该都是有用的。但是一开始我试用代码去关闭进程,发现都是无效。挣扎了许久,从根源上找问题。关闭进程,最终执行的都是相当于cmd运行里,执行的代码。因此,会不会是本地执行的有问题,不能够关进程呢?果断试一下,照着百度来的命令,在cmd中敲一敲。果然,敲完tasklist命令。提示tasklist不是内部或外部命令啥的。百度了下,解决方法有挺多的。找了下本地的文件,发现是有tasklist这个文件的,那就奇怪了,怎么会提示不是命令呢。 双击运行了tasklist.exe文件,发现可以执行。(路径是c.windows.system32).恍然大悟 是不是没有配置环境变量造成的,因为之前r语言在cmd中运行,也是提示不是命令,配置具体环境变量后,就可以使用了。果断尝试一下,果然,配置完task的环境变量后,再输入tasklist,就列出了系统的进程。再根据网络上taskkill的方式进行杀进程,发现不行。通过查询命令 taskkill /?进行关闭进程命令查看。找到正确的杀进程的命令,也成功杀掉了rserve.exe的进程。再回到servlet进行杀进程的操作。果然,操作成功。命令是:

 Runtime.getRuntime().exec("Taskkill /f /im Rserve.exe /t");
至此,开启进程,关闭进程,开始连接,使用r语言进行数据的聚类分析等,均已通过。

菜鸟便开始下一步的工作了。纯思路手工码字,练练打字速度。


原创粉丝点击