从原生矩阵格式转换,烫伤

时间:2013-11-17 14:44:35

标签: scala hadoop matrix scalding

所以这个问题与问题Transforming matrix format, scalding

有关

但是现在,我想进行背部操作。所以我可以这样做:

Tsv(in, ('row, 'col, 'v))
  .read
  .groupBy('row) { _.sortBy('col).mkString('v, "\t") }
  .mapTo(('row, 'v) -> ('c)) { res : (Long, String) =>
    val (row, v) = res
    v }
  .write(Tsv(out))

但是,在那里,我们遇到零问题。我们知道,烫伤会跳过零值字段。所以我们得到了矩阵:

1   0   8   
4   5   6   
0   8   9

烫金格式是:

1   1   1
1   3   8
2   1   4
2   2   5
2   3   6
3   2   8
3   3   9

使用我上面写的函数我们只能得到:

1   8
4   5   6
8   9

这是不正确的。那么,我该如何处理呢?我看到两种可能的变体:

  1. 找到方法,添加零(实际上,不知道如何插入数据)
  2. 用自己的矩阵格式编写自己的操作(这是不可取的,因为我对Scalding矩阵操作感兴趣,并且不想自己编写所有这些操作)
  3. 有没有一些方法,我可以避免在矩阵中跳过零?

1 个答案:

答案 0 :(得分:1)

Scalding存储数据的稀疏表示。如果你想输出一个密集矩阵(首先,它不会扩展,因为行数会比某些点上的内存大),你需要枚举所有的行和列:

// First, I highly suggest you use the TypedPipe api, as it is easier to get
// big jobs right generally

val mat = // has your matrix in 'row1, 'col1, 'val1
def zero: V = // the zero of your value type 
val rows = IterableSource(0 to 1000, 'row)
val cols = IterableSource(0 to 2000, 'col)
rows.crossWithTiny(cols)
  .leftJoinWithSmaller(('row, 'col) -> ('row1, 'col1), mat)
  .map('val1 -> 'val1) { v: V =>
    if(v == null) // this value should be 0 in your type:
      zero
    else
      v
  }
  .groupBy('row) { 
    _.toList[(Int, V)](('col, 'val1) -> 'cols)
  }
  .map('cols -> 'cols) { cols: List[(Int, V)] =>
    cols.sortBy(_._1).map(_._2).mkString("\t")
  }
  .write(TypedTsv[(Int, String)]("output"))