将CSV文件列中的类似项目分组为主键

时间:2014-08-18 12:09:39

标签: java csv

我有一个大型CSV文件,其数据与此类似

User ID       Group
ABC           Group1   
DEF           Group2
ABC           Group3
GHI           Group4
XYZ           Group2
UVW           Group5
XYZ           Group1
ABC           Group1
DEF           Group2

我需要对这些项目进行分组,以便在用户ID中重复组属性的次数,并获得一个值

ABC   Group1 ->2
ABC   Group3 ->1
DEF   Group2 ->2
GHI   Group4 ->1
UVW   Group5 ->1
XYZ   Group2 ->1
XYZ   Group1 ->1

是否有任何聚类算法可以做到这一点。

3 个答案:

答案 0 :(得分:1)

一个非常简单的解决方案是使用Guava的TreeMultiset:http://docs.guava-libraries.googlecode.com/git-history/release/javadoc/com/google/common/collect/TreeMultiset.html

使用字段userId和group创建一个类UserGroup,并通过首先在userId上进行比较然后在group上进行比较,让它实现Comparable。

读入csv文件,每行创建一个UserGroup并将其添加到MultiSet,

要获得结果,请使用MultiSet.iterator(),并输入entry.getElement()和entry.getCount()。

如果您获得内存不足,并且无法分配足够的内存,则可以使用外部(合并)排序https://code.google.com/p/externalsortinginjava/

答案 1 :(得分:1)

在你的情况下,如果你不想将所有数据存储在内存中,我会做这样的事情:

public class Tester {
public static Multiset<String> getMultisetFromCSV(String csvFileName, String lineDelimiter) throws IOException {
    Multiset<String> mapper = TreeMultiset.create();


    BufferedReader reader = null;

    try {
        reader = new BufferedReader(new FileReader(csvFileName));

        String[] currLineSplitted;

        while(reader.ready()) {
            currLineSplitted = reader.readLine().split(lineDelimiter);
            mapper.add(currLineSplitted[0] + "-" + currLineSplitted[1]);
        }

        return mapper;
    } finally {
        if(reader != null)
            reader.close();
    }

}

public static void main(String[] args) throws IOException {
    Multiset<String> set = getMultisetFromCSV("csv", ",");

    for(String key : set.elementSet()) {
        System.out.println(key + " : " + set.count(key));
    }


}

}

通过这种方式,您可以非常轻松地构建地图。之后,对于每个键,您可以使用count method计算与其关联的项目数。

答案 2 :(得分:1)

使用Java 8,您可以编写如下内容:

Map<String, Long> userGroup = Files.lines(csvFile, UTF_8)
                .skip(1) //skip headers
                .map(s -> s.split("\\s+")) //split on space
                .map(array -> array[0] + " " + array[1]) //user + " " + group
                //collect into a TreeMap, for sorting
                //the key is the user/group and the value the number of occurences
                .collect(groupingBy(ug -> ug, TreeMap::new, counting()));

注意:需要以下静态导入:import static java.util.stream.Collectors.counting;import static java.util.stream.Collectors.groupingBy;