目前,我一次将一个实例从一个数据集复制到另一个数据集。有没有办法做到这一点,以便字符串映射保持不变? mergeInstances水平工作,是否有等效的垂直合并?
这是我用于将多个arff文件中相同结构的数据集读取到一个大型数据集中的循环的一个步骤。必须有一种更简单的方法。
Instances iNew = new ConverterUtils.DataSource(name).getDataSet();
for (int i = 0; i < iNew.numInstances(); i++) {
Instance nInst = iNew.instance(i);
inst.add(nInst);
}
答案 0 :(得分:4)
如果您想要一个完全自动化的方法,也可以正确复制字符串和名义属性,您可以使用以下函数:
public static Instances merge(Instances data1, Instances data2)
throws Exception
{
// Check where are the string attributes
int asize = data1.numAttributes();
boolean strings_pos[] = new boolean[asize];
for(int i=0; i<asize; i++)
{
Attribute att = data1.attribute(i);
strings_pos[i] = ((att.type() == Attribute.STRING) ||
(att.type() == Attribute.NOMINAL));
}
// Create a new dataset
Instances dest = new Instances(data1);
dest.setRelationName(data1.relationName() + "+" + data2.relationName());
DataSource source = new DataSource(data2);
Instances instances = source.getStructure();
Instance instance = null;
while (source.hasMoreElements(instances)) {
instance = source.nextElement(instances);
dest.add(instance);
// Copy string attributes
for(int i=0; i<asize; i++) {
if(strings_pos[i]) {
dest.instance(dest.numInstances()-1)
.setValue(i,instance.stringValue(i));
}
}
}
return dest;
}
请注意,以下条件应保留(未在功能中检查):
要动态修改data2的名义属性的值以匹配data1的值,您可以使用:
data2.renameAttributeValue(
data2.attribute("att_name_in_data2"),
"att_value_in_data2",
"att_value_in_data1");
答案 1 :(得分:1)
为什么不制作一个包含两个原件数据的新ARFF文件?一个简单的
cat 1.arff > tmp.arff
tail -n+20 2.arff >> tmp.arff
其中20
被替换为你的arff标题长多少行。然后,这将生成一个包含所有所需实例的新arff文件,您可以使用现有代码读取此新文件:
Instances iNew = new ConverterUtils.DataSource(name).getDataSet();
您还可以使用以下文档在命令行上调用weka:http://old.nabble.com/how-to-merge-two-data-file-a.arff-and-b.arff-into-one-data-list--td22890856.html
java weka.core.Instances append filename1 filename2 > output-file
但是,文档http://weka.sourceforge.net/doc.dev/weka/core/Instances.html#main%28java.lang.String中没有任何功能允许您在Java代码中本地附加多个arff文件。从Weka 3.7.6开始,附加两个arff文件的代码是:
// read two files, append them and print result to stdout
else if ((args.length == 3) && (args[0].toLowerCase().equals("append"))) {
DataSource source1 = new DataSource(args[1]);
DataSource source2 = new DataSource(args[2]);
String msg = source1.getStructure().equalHeadersMsg(source2.getStructure());
if (msg != null)
throw new Exception("The two datasets have different headers:\n" + msg);
Instances structure = source1.getStructure();
System.out.println(source1.getStructure());
while (source1.hasMoreElements(structure))
System.out.println(source1.nextElement(structure));
structure = source2.getStructure();
while (source2.hasMoreElements(structure))
System.out.println(source2.nextElement(structure));
}
因此,看起来Weka本身只是遍历数据集中的所有实例并打印它们,代码使用相同的过程。
答案 2 :(得分:1)
另一种可能的解决方案是使用java.util.AbstractCollection中的addAll,因为Instances实现了它。
instances1.addAll(instances2);
答案 3 :(得分:0)
我刚刚与weka.core.Instaces
,innerJoin
,leftJoin
,fullJoin
和update
等方法共享了一个扩展的union
类。< / p>
table1.makeIndex(table1.attribute("Continent_ID");
table2.makeIndex(table2.attribute("Continent_ID");
Instances result = table1.leftJoin(table2);
实例可以有不同数量的属性,如果需要,NOMINAL
和STRING
变量的级别会合并在一起。
源代码和一些例子在GitHub上:weka.join。