我正在尝试使用apache.commons.math库来计算将R脚本转换为
java脚本.可以使用
org.apache.commons.math.analysis.interpolation.LoessInterpolator代替
R loess吗?我得不到同样的结果.
编辑.
这里是一个java程序,它创建一个随机数组(x,y),并用LoessInterpolator或者调用R来计算黄土.最后打印结果.
import java.io.*; import java.util.Random; import org.apache.commons.math.analysis.interpolation.LoessInterpolator; public class TestLoess { private String RScript="/usr/local/bin/Rscript"; private static class ConsummeInputStream extends Thread { private InputStream in; ConsummeInputStream(InputStream in) { this.in=in; } @Override public void run() { try { int c; while((c=this.in.read())!=-1) System.err.print((char)c); } catch(IOException err) { err.printStackTrace(); } } } TestLoess() { } private void run() throws Exception { int num=100; Random rand=new Random(0L); double x[]=new double[num]; double y[]=new double[x.length]; for(int i=0;i< x.length;++i) { x[i]=rand.nextDouble()+(i>0?x[i-1]:0); y[i]=Math.sin(i)*100; } LoessInterpolator loessInterpolator=new LoessInterpolator( 0.75,//bandwidth,2//robustnessIters ); double y2[]=loessInterpolator.smooth(x,y); Process proc=Runtime.getRuntime().exec( new String[]{RScript,"-"} ); ConsummeInputStream errIn=new ConsummeInputStream(proc.getErrorStream()); BufferedReader stdin=new BufferedReader(new InputStreamReader(proc.getInputStream())); PrintStream out=new PrintStream(proc.getOutputStream()); errIn.start(); out.print("T<-as.data.frame(matrix(c("); for(int i=0;i< x.length;++i) { if(i>0) out.print(','); out.print(x[i]+","+y[i]); } out.println("),ncol=2,byrow=TRUE))"); out.println("colnames(T)<-c('x','y')"); out.println("T2<-loess(y ~ x,T)"); out.println("write.table(residuals(T2),'',col.names= F,row.names=F,sep='\\t')"); out.flush(); out.close(); double y3[]=new double[x.length]; for(int i=0;i< y3.length;++i) { y3[i]=Double.parseDouble(stdin.readLine()); } System.out.println("X\tY\tY.java\tY.R"); for(int i=0;i< y3.length;++i) { System.out.println(""+x[i]+"\t"+y[i]+"\t"+y2[i]+"\t"+y3[i]); } } public static void main(String[] args) throws Exception { new TestLoess().run(); } }
编译& EXEC:
javac -cp commons-math-2.2.jar TestLoess.java && java -cp commons-math-2.2.jar:. TestLoess
输出:
X Y Y.java Y.R 0.730967787376657 0.0 6.624884763714674 -12.5936186703287 0.9715042030481429 84.14709848078965 6.5263049649584 71.9725380029913 1.6089216283982513 90.92974268256818 6.269100654071115 79.839773167581 2.159358633515885 14.112000805986721 6.051308261720918 3.9270340708818 2.756903911313087 -75.68024953079282 5.818424835586378 -84.9176311089431 3.090122310789737 -95.89242746631385 5.689740879461759 -104.617807889069 3.4753114955304554 -27.941549819892586 5.541837854229562 -36.0902352062634 4.460153035730264 65.6986598718789 5.168028655980764 58.9472823439219 5.339335553602744 98.93582466233818 4.840314399516663 93.3329030534449 6.280584733084859 41.21184852417566 4.49531113985498 36.7282165788057 6.555538699120343 -54.40211108893698 4.395343460231256 -58.5812856445538 6.68443584999412 -99.99902065507035 4.348559404444451 -104.039069260889 6.831037507640638 -53.657291800043495 4.295400167908642 -57.5419313320511 6.854275630124528 42.016703682664094 4.286978656933373 38.1564179414478 7.401015387322993 99.06073556948704 4.089252482141094 95.7504087842369 8.365502247999844 65.02878401571168 3.7422883733498726 62.5865641279576 8.469992934250815 -28.790331666506532 3.704793544880599 -31.145867173504 9.095139297716374 -96.13974918795569 3.4805388562453574 -98.0047896609079 9.505935493207435 -75.09872467716761 3.3330472034239405 -76.6664588290508
y的输出值在R和Java之间显然不一样; TheY.R列看起来不错(它接近原始的Y列).为了得到Y.java〜Y.R,我该怎么改?
解决方法
您需要更改三个输入参数的默认值,使Java和R版本相同:
> Java LoessInterpolator只进行线性局部多项式回归,但R支持线性(度= 1),二次(度= 2)和奇数度= 0选项.所以你需要在R中指定degree = 1来与Java相同.> LoessInterpolator默认迭代次数DEFAULT_ROBUSTNESS_ITERS = 2,但是R默认迭代= 4.所以你需要在R中设置control = loess.control(iterations = X)(X是迭代次数).> LoessInterpolator默认为DEFAULT_BANDWIDTH = 0.3,但R默认为span = 0.75.