Author: jcouteau Date: 2009-04-30 12:10:02 +0000 (Thu, 30 Apr 2009) New Revision: 70 Added: lutinj2r/trunk/src/main/java/org/codelutin/j2r/types/ lutinj2r/trunk/src/main/java/org/codelutin/j2r/types/RDataFrame.java lutinj2r/trunk/src/test/java/org/codelutin/j2r/DataframeTest.java Log: Adding data.frame data type + tests. Added: lutinj2r/trunk/src/main/java/org/codelutin/j2r/types/RDataFrame.java =================================================================== --- lutinj2r/trunk/src/main/java/org/codelutin/j2r/types/RDataFrame.java (rev 0) +++ lutinj2r/trunk/src/main/java/org/codelutin/j2r/types/RDataFrame.java 2009-04-30 12:10:02 UTC (rev 70) @@ -0,0 +1,254 @@ +package org.codelutin.j2r.types; + +import java.io.Serializable; +import java.util.Vector; + +import org.codelutin.j2r.REngine; +import org.codelutin.j2r.RException; + +public class RDataFrame { + + private Vector<String> names; + private Vector<String> rowNames; + private Vector<Vector<? extends Serializable>> data; + private String variable; + + public RDataFrame() { + super(); + this.names = new Vector<String>(); + this.rowNames = new Vector<String>(); + this.data = new Vector<Vector<? extends Serializable>>(); + this.variable = ""; + } + + public RDataFrame(Vector<String> names, Vector<String> rowNames, + Vector<Vector<? extends Serializable>> data, REngine engine, + String variable) throws RException { + super(); + this.names = names; + this.rowNames = rowNames; + this.data = (Vector<Vector<? extends Serializable>>) data; + this.variable = variable; + assignTo(variable, engine); + } + + /** + * Method to get the names of the vectors of the R data.frame (there is no + * synchronizing with R, use the synchro() method to synchronize data with R + * before using this method if you think data may have changed. + * + * @return a vector of strings containing the names of each vector of the R + * data.frame + */ + public Vector<String> getNames() { + return names; + } + + /** + * Method to assign names of the vectors of the R data.frame (the names will + * then be synchronized with R) + * + * @param names + * a vector containing the names of the vector of the R + * data.frame + * @param engine + * a REngine where the R session is located. + * @throws RException + */ + public void setNames(Vector<String> names, REngine engine) + throws RException { + this.names = names; + assignNames(engine); + } + + /** + * Method to get the names of the rows of the R data.frame (there is no + * synchronizing with R, use the synchro() method to synchronize data with R + * before using this method if you think data may have changed. + * + * @return a vector of strings containing the names of each row of the R + * data.frame + */ + public Vector<String> getRowNames() { + return rowNames; + } + + /** + * Method to assign names of the rows of the R data.frame (the names will + * then be synchronized with R) + * + * @param rowNames + * a vector containing the names of the rows of the R data.frame + * @param engine + * a REngine where the R session is located. + * @throws RException + */ + public void setRowNames(Vector<String> rowNames, REngine engine) + throws RException { + this.rowNames = rowNames; + assignRowNames(engine); + } + + /** + * Method to get the vectors of the R data.frame (there is no synchronizing + * with R, use the synchro() method to synchronize data with R before using + * this method if you think data may have changed. + * + * @return a Vector containing the vectors of the R data.frame + */ + public Vector<Vector<? extends Serializable>> getData() { + return data; + } + + /** + * Method to assign the data of the R data.frame (the data will then be + * synchronized with R) + * + * @param data + * a Vector of Vectors, containing each vector of the R + * data.frame + * @param engine + * a REngine where the R session is located. + * @throws RException + */ + public void setData(Vector<Vector<? extends Serializable>> data, + REngine engine) throws RException { + this.data = data; + assignData(engine); + } + + /** + * Method to assign this data.frame to a variable in R. + * + * @param variable + * name of the variable + * @param engine + * a REngine where the R session is located. + * @throws RException + */ + public void assignTo(String variable, REngine engine) throws RException { + + this.variable = variable; + assignData(engine); + assignRowNames(engine); + assignNames(engine); + + } + + /** + * Method to get a data.frame from a variable in R. + * + * @param variable + * name of the data.frame in R + * @param engine + * a REngine where the R session is located. + * @throws RException + */ + public void getFrom(String variable, REngine engine) throws RException { + this.variable = variable; + rowNames.clear(); + names.clear(); + data.clear(); + String[] rowNamesArray = (String[]) engine.eval("row.names(" + + this.variable + ")"); + for (int i = 0; i < rowNamesArray.length; i++) { + rowNames.add(rowNamesArray[i]); + } + String[] namesArray = (String[]) engine.eval("names(" + this.variable + + ")"); + for (int i = 0; i < namesArray.length; i++) { + names.add(namesArray[i]); + } + + Integer dataframelength = (Integer) engine.eval("length(" + + this.variable + ")"); + + for (int i = 0; i < dataframelength; i++) { + Integer vectorlength = (Integer) engine.eval("length(" + + this.variable + "[," + (i + 1) + "])"); + Vector<Serializable> thisColumn = new Vector<Serializable>(); + for (int j = 0; j < vectorlength; j++) { + thisColumn.add((Serializable) engine.eval(this.variable + "[" + + (i + 1) + "," + (j + 1) + "]")); + } + data.add(thisColumn); + } + + } + + /** + * Synchronization with R method. This method updates the content of the + * data.frame from R. All local changes are lost. + * + * @param engine + * a REngine where the R session is located. + * @throws RException + */ + public void check(REngine engine) throws RException { + getFrom(variable, engine); + } + + /** + * Send names changes to R + * + * @param engine + * @throws RException + */ + private void assignNames(REngine engine) throws RException { + String vectorNames = "names(" + this.variable + ")<-c("; + for (int i = 0; i < names.size(); i++) { + vectorNames = vectorNames + "\"" + names.get(i) + "\"" + ","; + } + vectorNames = vectorNames.substring(0, vectorNames.length() - 1) + ")"; + engine.voidEval(vectorNames); + } + + /** + * Send row names changes to R + * + * @param engine + * a REngine where the R session is located. + * @throws RException + */ + private void assignRowNames(REngine engine) throws RException { + String vectorRowNames = "row.names(" + this.variable + ")<-c("; + for (int i = 0; i < rowNames.size(); i++) { + vectorRowNames = vectorRowNames + "\"" + rowNames.get(i) + "\"" + + ","; + } + vectorRowNames = vectorRowNames.substring(0, + vectorRowNames.length() - 1) + + ")"; + engine.voidEval(vectorRowNames); + } + + /** + * Send data changes to R + * + * @param engine + * a REngine where the R session is located. + * @throws RException + */ + private void assignData(REngine engine) throws RException { + String dataframe = variable + "<-data.frame("; + for (int i = 0; i < data.size(); i++) { + dataframe = dataframe + "data" + i + ","; + String datai = "data" + i + "<-c("; + for (int j = 0; j < data.get(i).size(); j++) { + datai = datai + data.get(i).get(j) + ","; + } + datai = datai.substring(0, datai.length() - 1) + ")"; + engine.voidEval(datai); + + } + dataframe = dataframe.substring(0, dataframe.length() - 1) + ")"; + engine.voidEval(dataframe); + } + + //TODO method set attributes, get attributes + + //TODO method add attribute, remove attribute + + //TODO check data consistency. + +} Added: lutinj2r/trunk/src/test/java/org/codelutin/j2r/DataframeTest.java =================================================================== --- lutinj2r/trunk/src/test/java/org/codelutin/j2r/DataframeTest.java (rev 0) +++ lutinj2r/trunk/src/test/java/org/codelutin/j2r/DataframeTest.java 2009-04-30 12:10:02 UTC (rev 70) @@ -0,0 +1,158 @@ +/* *##% Lutin Java-2-R library + * Copyright (C) 2006 - 2008 CodeLutin + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. ##%*/ + +package org.codelutin.j2r; + +import java.io.Serializable; +import java.util.Vector; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.codelutin.j2r.types.RDataFrame; +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +public class DataframeTest { + + private static Log log = LogFactory.getLog(DataframeTest.class); + + private REngine engine; + + @Before + public void setUp() throws Exception { + LutinTimer init = new LutinTimer(); + init.startTiming(); + if (engine == null) { + engine = new RProxy(); + } + } + + @After + public void tearDown() throws Exception { + engine.terminate(); + } + + @Test + public void testDataFrameCreation() throws Exception { + //This test is also a test for all the setters... + //they work the same way and use the same internal methods. + Vector<String> names = new Vector<String>(); + names.add("column1"); + names.add("column2"); + + Vector<String> rowNames = new Vector<String>(); + rowNames.add("row 1"); + rowNames.add("row 2"); + rowNames.add("row 3"); + + Vector<Double> column1 = new Vector<Double>(); + column1.add(3.0); + column1.add(4.5); + column1.add(0.01); + + Vector<Double> column2 = new Vector<Double>(); + column2.add(1.0); + column2.add(5555555555555555555555.0); + column2.add(3.0); + + Vector<Vector<? extends Serializable>> data = new Vector<Vector<? extends Serializable>>(); + data.add(column1); + data.add(column2); + + RDataFrame testDataFrame = new RDataFrame(names, rowNames, data, + engine, "test"); + //Test data + Assert.assertEquals(new Double(3.0), (Double) engine.eval("test[1,1]")); + Assert.assertEquals(new Double(4.5), (Double) engine.eval("test[2,1]")); + Assert + .assertEquals(new Double(0.01), (Double) engine + .eval("test[3,1]")); + Assert.assertEquals(new Double(1.0), (Double) engine.eval("test[1,2]")); + Assert.assertEquals(new Double(5555555555555555555555.0), + (Double) engine.eval("test[2,2]")); + Assert.assertEquals(new Double(3.0), (Double) engine.eval("test[3,2]")); + //Test names + Assert.assertEquals("column1", (String) engine.eval("names(test)[1]")); + Assert.assertEquals("column2", (String) engine.eval("names(test)[2]")); + //Test row names + Assert + .assertEquals("row 1", (String) engine + .eval("row.names(test)[1]")); + Assert + .assertEquals("row 2", (String) engine + .eval("row.names(test)[2]")); + Assert + .assertEquals("row 3", (String) engine + .eval("row.names(test)[3]")); + } + + @Test + public void testGetDataFrame() throws Exception { + //This test is also a test for all the setters... + //they work the same way and use the same internal methods. + Vector<String> names = new Vector<String>(); + names.add("column1"); + names.add("column2"); + + Vector<String> rowNames = new Vector<String>(); + rowNames.add("row 1"); + rowNames.add("row 2"); + rowNames.add("row 3"); + + Vector<Double> column1 = new Vector<Double>(); + column1.add(3.0); + column1.add(4.5); + column1.add(0.01); + + Vector<Double> column2 = new Vector<Double>(); + column2.add(1.0); + column2.add(5555555555555555555555.0); + column2.add(3.0); + + Vector<Vector<? extends Serializable>> data = new Vector<Vector<? extends Serializable>>(); + data.add(column1); + data.add(column2); + + RDataFrame testDataFrame = new RDataFrame(names, rowNames, data, + engine, "test"); + RDataFrame dataframe2 = new RDataFrame(); + dataframe2.getFrom("test", engine); + //Test data + Assert.assertEquals(new Double(3.0), (Double) engine.eval("test[1,1]")); + Assert.assertEquals(new Double(4.5), (Double) engine.eval("test[2,1]")); + Assert + .assertEquals(new Double(0.01), (Double) engine + .eval("test[3,1]")); + Assert.assertEquals(new Double(1.0), (Double) engine.eval("test[1,2]")); + Assert.assertEquals(new Double(5555555555555555555555.0), + (Double) engine.eval("test[2,2]")); + Assert.assertEquals(new Double(3.0), (Double) engine.eval("test[3,2]")); + //Test names + Assert.assertEquals("column1", dataframe2.getNames().get(0)); + Assert.assertEquals("column2", dataframe2.getNames().get(1)); + //Test row names + Assert + .assertEquals("row 1", dataframe2.getRowNames().get(0)); + Assert + .assertEquals("row 2", dataframe2.getRowNames().get(1)); + Assert + .assertEquals("row 3", dataframe2.getRowNames().get(2)); + } + +}