Pergunta

Estou tentando calcular a conversão de um script R para java usando o apache.commons.math biblioteca.Eu posso usar org.apache.commons.math.análise.interpolation.LoessInterpolator no lugar de R loess ?Não consigo obter o mesmo resultado.

EDITAR.

aqui está um programa java que cria um array aleatório (x,y) e calcula o loess com LoessInterpolator ou chamando R.Ao final, os resultados são impressos.

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();
        }
    }

compilação e execução:

javac -cp commons-math-2.2.jar TestLoess.java && java -cp commons-math-2.2.jar:. TestLoess

saída:

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

os valores de saída para y claramente não são os mesmos entre R e Java;A coluna Y.R parece boa (está próxima da coluna Y original).Como devo mudar isso para obter Y.java ~ Y.R ?

Foi útil?

Solução

Você precisa alterar os valores padrão de três parâmetros de entrada para tornar as versões Java e R idênticas:

  1. O Java LoessInterpolator faz apenas regressão polinomial local linear, mas R suporta linear (grau = 1), quadrático (grau = 2) e uma opção estranha de grau = 0.Então você precisa especificar degree=1 em R para ser idêntico ao Java.

  2. LoessInterpolator padroniza o número de iterações DEFAULT_ROBUSTNESS_ITERS=2, mas o padrão R iterations=4.Então você precisa definir control = loess.control(iterations=X) em R (X é o número de iterações).

  3. Padrões do LoessInterpolator DEFAULT_BANDWIDTH=0.3 mas R é o padrão span=0.75.

Outras dicas

Não posso falar pela implementação do Java, mas lowess tem vários parâmetros que controlam a largura de banda do ajuste.A menos que você esteja ajustando os mesmos parâmetros de controle, você deve esperar que os resultados sejam diferentes.Minha recomendação sempre que as pessoas estiverem suavizando dados é traçar os dados originais, bem como o ajuste, e decidir por si mesmo quais parâmetros de controle geram a compensação desejada entre fidelidade aos dados e suavização (também conhecida como remoção de ruído).

Existem dois problemas aqui.Primeiro, se você plotar os dados que está gerando, eles parecerão quase aleatórios e o ajuste gerado pelo loess em R será muito ruim, por exemplo.

plot(T$x, T$y)
lines(T$s, T2$fitted, col="blue", lwd=3)

plot of the data generated by the Java code above with a loess fit generated by R

Então, no seu script R, você está escrevendo os resíduos, não as previsões, nesta linha

out.println("write.table(residuals(T2),'',
   col.names= F,row.names=F,sep='\\t')");

você precisa mudar residuals(T2) para predict(T2) por exemplo.

out.println("write.table(predict(T2),'',
   col.names= F,row.names=F,sep='\\t')");

Portanto, foi por puro acaso em seu exemplo de código que as primeiras linhas de resíduos gerados por R parecessem adequadas.

Para mim, se eu tentar ajustar alguns dados mais apropriados, Java e R retornarão resultados semelhantes, mas não idênticos.Também descobri que os resultados seriam mais próximos se eu não ajustasse o padrão robustezIter configurações.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top