如何从包含不可读字符的spark数据帧中过滤掉行

时间:2016-11-24 10:49:42

标签: scala apache-spark dataframe apache-spark-sql

我正在阅读包含设备ID,imei等字段的镶木地板文件。 这个镶木地板文件是通过读取由cascading.tuple.Tuple(s)组成的序列文件编写的。

有些行包含我想完全抛弃的不可读字符。

以下是我阅读文件的方式:

val sparkSession = SparkSession.builder().master(sparkMaster).appName(sparkAppName).config("spark.driver.memory", "32g").getOrCreate()

sparkSession.sparkContext.hadoopConfiguration.set("io.serializations", "cascading.tuple.hadoop.TupleSerialization") 

val df=sparkSession.read.parquet("hdfs://**.46.**.2*2:8020/test/oldData.parquet")

df.printSchema()

val filteredDF=df.select($"$DEVICE_ID", $"$DEVICE_ID_NEW", $"$IMEI”, $”$WIFI_MAC_ADDRESS", $"$BLUETOOTH_MAC_ADDRESS", $"$TIMESTAMP").filter($"$TIMESTAMP" > 1388534400 && $"$TIMESTAMP" < 1483228800)

filteredDF.show(100)

import org.apache.spark.sql.functions.{udf,col,regexp_replace,trim}

val len=udf{ColVal:String => ColVal.size}

val new1DF=filteredDF.select(trim(col("deviceId")))

new1DF.show(100)

val newDF=new1DF.filter((len(col("deviceId")) <20))

newDF.show(100)

即使对长度小于20的设备ID应用过滤器,我仍然会得到那些设备ID非常长的行,其中包含大部分空格和不可读的字符。

有人可以指出一些可以帮助我过滤这些行的线索。

我还尝试过滤掉包含特价的设备ID。使用这个:

df.filter($&#34; $ DEVICE_ID&#34; rlike&#34; / [^ \ uFFFD] / g&#34;)

我有一个空的数据框。

SCHEMA:

root
 |-- deviceId: string (nullable = true)
 |-- deviceIdNew: string (nullable = true)
 |-- imei: string (nullable = true)
 |-- wifiMacAddress: string (nullable = true)
 |-- bluetoothMacAddress: string (nullable = true)
 |-- timestamp: long (nullable = true)

具有无法识别字符的行:

+--------------------+
|      trim(deviceId)|
+--------------------+
|                    |
|+~C���...|
|���
    Cv�...|
|���
    Cv�...|
|             �#Inten|
|                �$
                   �|
|                    |
|                    |
|                    |
|                    |
|    0353445a712d877b|
|    0577bc8a29754939|
|    0577bc8a29754939|
|    0577bc8a29754939|
|    0577bc8a29754939|
|    0577bc8a29754939|
|    0577bc8a29754939|
|    0577bc8a29754939|
|    08bdae9e37b48080|

UNREADABLE ROW VALUES

2 个答案:

答案 0 :(得分:3)

    val filteredDF=df.select("deviceId")
                     .filter((len(col("deviceId")) <17))
                     .filter($"$DEVICE_ID" rlike "^([A-Z]|[0-9]|[a-z])+$") 

解决了这个问题。

我之前没有使用的是正则表达式外卡^用于比赛开始,$用于比赛结束。这确保只有具有完全匹配deviceId值的行才能通过过滤器。

This website确实帮助我生成并测试了所需的正则表达式。

答案 1 :(得分:0)

您可以按正则表达式过滤。 例如,您可以使用regex_replace将具有不可读字符的所有字符(即除了字母数字或可打印的所有内容或任何您决定的内容)替换为具有某些值(例如,21个字符常量或甚至空字符串),然后根据此进行过滤。

相关问题