2

目前,我一次将一个实例从一个数据集复制到另一个数据集。有没有办法做到这一点,使字符串映射保持不变?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);
}
4

4 回答 4

5

如果您想要一个完全自动化的方法,也可以正确复制字符串和名义属性,您可以使用以下函数:

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");
于 2012-09-10T21:32:01.180 回答
1

为什么不制作一个包含两个原始数据的新 ARFF 文件?一个简单的

cat 1.arff > tmp.arff
tail -n+20 2.arff >> tmp.arff

where20被您的 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中没有允许您在本地附加多个 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 本身只是简单地遍历数据集中的所有实例并打印它们,这与您的代码使用的过程相同。

于 2012-05-27T21:58:40.483 回答
1

另一种可能的解决方案是使用 java.util.AbstractCollection 中的 addAll,因为实例实现了它。

instances1.addAll(instances2);
于 2013-10-16T20:35:09.240 回答
0

我刚刚共享了一个扩展weka.core.Instaces类,其中包含innerJoinleftJoin、和.fullJoinupdateunion

table1.makeIndex(table1.attribute("Continent_ID");
table2.makeIndex(table2.attribute("Continent_ID");
Instances result = table1.leftJoin(table2);

实例可以具有不同数量的属性、级别NOMINALSTRING变量,如有必要,可以将它们合并在一起。

来源和一些示例在 GitHub 上:weka.join

于 2015-02-09T10:14:30.463 回答