2016-04-18 2 views
1

私は様々な列を含むDataFrameを持っています。 1つの列には、Map [Integer、Integer []]が含まれています。 それは{ 2345 -> [1,34,2]; 543 -> [12,3,2,5]; 2 -> [3,4]}のようになります 私がする必要があるのはいくつかのキーをフィルターにかけることです。 私は、このようなすなわちSpark DataFrameのMapTypeを抽出またはフィルタリングする

col(x).keySet.isin(javaIntSet) 

ことをフィルタするべきで、Javaの整数の集合(javaIntSet)を持っています。上記のマップにはキー2と543のみが含まれ、他の2つは含まれていない必要があり、フィルタリング後に{543 -> [12,3,2,5]; 2 -> [3,4]}のように表示されます。

Java列クラスの使用方法に関するドキュメントはまばらです。 col(x)を抽出して、javaでフィルタリングしてから、セルデータをフィルタリングされたマップに置き換えることができます。または、私が見落としている列の便利な機能がありますか? 書くことができますUDF2<Map<Integer, Integer[]>,Set<Integer>,Map<Integer,Integer[]> UDF1<String,String>と書くことができますが、もっと複雑なパラメータでどのように動作するかはわかりません。

一般に、javaIntSetは十数行で、通常は100未満の値です。マップには通常、一握りのエントリしかありません(通常は0-5)。

私はJavaでこれを行う必要があります(残念ながら)が、私はScalaに精通しています。自分自身をJavaに変換するScalaの答えは、すでに非常に役に立ちます。

答えて

2

UDFは必要ありません。 1できれいかもしれませんが、あなたが同じように簡単DataFrame.explodeでそれを行うことができます:

mapDf.explode($"map"){ 
    case Row(map: Map[Int,Int] @unchecked) => { 
    val newMap = map.filter(m => m._1 != 1) // <-- do filtering here 
    Seq(Tuple1(newMap)) 
    } 
}.show 
+---+--------------------+--------------------+ 
| id|     map|     _1| 
+---+--------------------+--------------------+ 
| 1|Map(1 -> 3, 2 -> ...|Map(2 -> 10, 3 -> 2)| 
| 2|Map(1 -> 12, 2 ->...|Map(2 -> 333, 3 -...| 
+---+--------------------+--------------------+ 

あなたがUDFをしたいなかった場合、それは次のようになります。

case class MapTest(id: Int, map: Map[Int,Int]) 
val mapDf = Seq(
    MapTest(1, Map((1,3),(2,10),(3,2))), 
    MapTest(2, Map((1,12),(2,333),(3,543))) 
).toDF("id", "map") 

mapDf.show 
+---+--------------------+ 
| id|     map| 
+---+--------------------+ 
| 1|Map(1 -> 3, 2 -> ...| 
| 2|Map(1 -> 12, 2 ->...| 
+---+--------------------+ 

次に、あなたが爆発使用することができますこれは:

val mapFilter = udf[Map[Int,Int],Map[Int,Int]](map => { 
    val newMap = map.filter(m => m._1 != 1) // <-- do filtering here 
    newMap 
}) 

mapDf.withColumn("newMap", mapFilter($"map")).show 
+---+--------------------+--------------------+ 
| id|     map|    newMap| 
+---+--------------------+--------------------+ 
| 1|Map(1 -> 3, 2 -> ...|Map(2 -> 10, 3 -> 2)| 
| 2|Map(1 -> 12, 2 ->...|Map(2 -> 333, 3 -...| 
+---+--------------------+--------------------+ 

DataFrame.explodeはやや複雑ですが、最終的にはより柔軟です。たとえば、元の行を2つの行に分割することができます.1つは、要素がフィルタされたマップを含む行、もう1つは逆のマップ、フィルタされた要素です。

+0

shame OPはこの回答を確認していません!非常に非常に良い例ダビデはあなたに感謝 – dedpo

関連する問題