2017-11-28 14 views
1

データが不正確に分割されているデータセットがあります。この結果、列数が不均一になります.1行あたりの列数は、1つのフィールドから発生するエラー数によって異なります。先頭に3つの二重引用符がある場合は、列が正しくないかどうかがわかります。列に3つの先行する二重引用符がある場合は、前の列と結合して左に移動します。Spark:条件付き結合/連結列ベースの先頭の文字

データのcsvをデータフレームにインポートします。このデータフレームは、以下の例のように作成されます。

例:

INPUT:

`+--+--------+----------+----------+---------+ 
|id | detail | context |  _c3 |  _c4| 
+---+--------+----------+----------+---------+ 
| 1 | {blah} | service | null  | null | 
| 2 | { blah | """ blah | """blah} | service | 
| 3 | { blah | """blah} | service | null | 
+---+--------+----------+----------+---------+` 

所望の出力:

`+--+------------------------+---------+ 
|id | detail     | context | 
+---+------------------------+---------+ 
| 1 | {blah}     | service | 
| 2 | { blah""" blah"""blah} | service | 
| 3 | { blah"""blah}   | service | 
+---+------------------------+---------+` 

私が何かしようとした - だけでなく、他のアプローチの束:

`df.filter(col("context").startsWith("\"\"\"")).select($"detail", lit(" "), $"context").collect()` 

私はそれが必要なものを完全には行いません。何か案は?ヘルプは大いに感謝しています:)

ありがとう!

答えて

1

これを修正する最も簡単な方法は、列をまとめて戻し、正しく解析することだと思います。これを行う1つの方法は、すべての列を結合するためにconcatを使用し、次にregexp_extractを使用して、個々の列として必要な部分を引き出します。たとえば:

case class MyRow(id: Int, detail: String, context: String, _c3: String, _c4: String) 
val data = Seq(
    MyRow(1, "{blah}", "service", "", ""), 
    MyRow(2, "{ blah", " \"\"\" blah", " \"\"\"blah}", "service"), 
    MyRow(3, "{ blah", "\"\"\"blah}", "service", "") 
) 

val df = sc.parallelize(data).toDF 

val columns = df.columns.filterNot(_ == "id") 

val nonulls = df.na.fill("") 
val combined = nonulls.select($"id", concat(columns.map(col):_*) as "data") 

val fixed = combined.withColumn("left", regexp_extract($"data", "(\\{.*\\})", 1)). 
       withColumn("right", regexp_extract($"data", "([^}]+$)", 1)) 

fixed.show(10, false) 

は、その出力をする必要があります

+---+-------------------------------+------------------------+-------+ 
|id |data       |left     |right | 
+---+-------------------------------+------------------------+-------+ 
|1 |{blah}service     |{blah}     |service| 
|2 |{ blah """ blah """blah}service|{ blah """ blah """blah}|service| 
|3 |{ blah"""blah}service   |{ blah"""blah}   |service| 
+---+-------------------------------+------------------------+-------+ 

I上記のコードでは、列が正しい順序で既にあると仮定しています。

これは最後に分割されています}。より複雑な解析が必要な場合は、必要に応じて解析するUDFを記述して、複数のフィールドのタプルを返すことができます。

+0

この例では3つの予期された列がありますが、実際の表には10以上の予想列があります。あなたはまだこのアプローチを採用しますか? – Keren

+0

私はこのアプローチで遊んできました。上記の表では、列は実際には ""ではなく ""ではありません。だから、これが実際に計算されるとき、あなたはいくつかの狂った探しの列を取得します...あなたはnullをどう扱うでしょうか? – Keren

+0

複数の列を連結するときに正しい順序であれば、任意の数の列を使用できます。また、nullを空の文字列に変換するDataFrameNaFunctions(特に塗りつぶし)だけが可能です。私はこれを行うための答えを更新しました。 – RyanW