使用Renjin将POJO对象的ArrayList转换为R数据帧

时间:2015-09-22 22:34:09

标签: java r renjin

我正在尝试使用Renjin根据Java程序中存在的数据构建模型。我有一个ArrayList POJO对象列表,其中每个属性都是Stringdoubleint。如果我拨打toString(),则记录如下:

Record{id='uibbd923e5929b43', countryCode='FR', revenue=3.14159, count=1}
Record{id='uicdd967e5942b55', countryCode='GB', revenue=0.07, count=49}
...

我实例化了R,在JVM中运行,如下所示:

ScriptEngineManager manager = new ScriptEngineManager();
ScriptEngine engine = manager.getEngineByName("Renjin");

...并将ArrayList条记录放入R:

engine.put("records", records);

在R中,记录存储为<externalptr>个对象的列表。可以看到存储在指针内的值的字符串表示,例如

engine.eval("print(data.frame(lapply(records, as.character), stringsAsFactors=FALSE))");

但是,我真的希望这些存储为具有正确数据类型的数据帧,而不是可以被视为字符串的外部指针列表。

如何将externalptr的列表转换为数据框?

更新

这是我的蹩脚解决方法,至少目前如此。将数据写入CSV:

CSVWriter writer = new CSVWriter(new FileWriter("tmp/output.csv"), '\t');    
writer.writeNext(new String[] {"id", "countryCode", "revenue", "count"});

    for (Record record : records){

        writer.writeNext(new String[]{record.getId(),
                record.getCountryCode(),
                record.getRevenue().toString(),
                record.getCount().toString()});
    }

    writer.close();

然后Renjin将CSV读入数据帧:

engine.eval("df <- read.table(\"tmp/output.csv\", header = TRUE)");

更新

目前,我决定使用Rserve,因为它提供了更大的灵活性。 Rserve(vs Renjin)的一个缺点是我们现在需要确保R正在运行并安装了必要的软件包。

1 个答案:

答案 0 :(得分:2)

这可能对于作为一个小帮助库组合起来很有用,但目前,你可以手动&#34;以下列方式在Java中逐步构建data.frame:

StringArrayVector.Builder id = new StringArrayVector.Builder();
StringArrayVector.Builder country = new StringArrayVector.Builder(); 
DoubleArrayVector.Builder revenue = new DoubleArrayVector.Builder();
for(Record record : records) {
   id.add(record.getId());
   country.add(record.getCountry());
   revenue.add(record.getRevenue());
}

ListVector.NamedBuilder myDf = new ListVector.NamedBuilder();
myDf.setAttribute(Symbols.CLASS, StringVector.valueOf("data.frame"));
myDf.setAttribute(Symbols.ROW_NAMES, new RowNamesVector(records.size()); 
myDf.add("id", id.build());
myDf.add("country", country.build());
myDf.add("revenue", revenue.build());

从上面可以看到,data.frame对象实际上只是一个列列表,因此需要花费一些时间来获取Java Bean的集合,这些集合基本上是基于行的格式。列的集合。

添加&#34; row.names&#34;同样重要。 nrow()等函数使用的属性来获取data.frame对象的维度。

上面的RowNamesVector是StringVector的一个专门实现,可以根据需要计算row.names&#34; 1&#34;,&#34; 2&#34;,&#34; 3&#34;等,而无需分配所有字符串的记忆。