使用列的长度过滤 DataFrame
Posted
技术标签:
【中文标题】使用列的长度过滤 DataFrame【英文标题】:Filtering DataFrame using the length of a column 【发布时间】:2016-02-15 04:34:52 【问题描述】:我想使用与列长度相关的条件过滤DataFrame
,这个问题可能很简单,但我在 SO 中没有找到任何相关问题。
更具体地说,我有一个DataFrame
,只有一个Column
ArrayType(StringType())
,我想使用长度作为过滤器过滤DataFrame
,我在下面拍摄了一个sn-p。
df = sqlContext.read.parquet("letters.parquet")
df.show()
# The output will be
# +------------+
# | tokens|
# +------------+
# |[L, S, Y, S]|
# |[L, V, I, S]|
# |[I, A, N, A]|
# |[I, L, S, A]|
# |[E, N, N, Y]|
# |[E, I, M, A]|
# |[O, A, N, A]|
# | [S, U, S]|
# +------------+
# But I want only the entries with length 3 or less
fdf = df.filter(len(df.tokens) <= 3)
fdf.show() # But it says that the TypeError: object of type 'Column' has no len(), so the previous statement is obviously incorrect.
我阅读了Column's Documentation,但没有发现任何对此事有用的属性。我很感激任何帮助!
【问题讨论】:
【参考方案1】:在 Spark >= 1.5 中,您可以使用 size
函数:
from pyspark.sql.functions import col, size
df = sqlContext.createDataFrame([
(["L", "S", "Y", "S"], ),
(["L", "V", "I", "S"], ),
(["I", "A", "N", "A"], ),
(["I", "L", "S", "A"], ),
(["E", "N", "N", "Y"], ),
(["E", "I", "M", "A"], ),
(["O", "A", "N", "A"], ),
(["S", "U", "S"], )],
("tokens", ))
df.where(size(col("tokens")) <= 3).show()
## +---------+
## | tokens|
## +---------+
## |[S, U, S]|
## +---------+
在 Spark
from pyspark.sql.types import IntegerType
from pyspark.sql.functions import udf
size_ = udf(lambda xs: len(xs), IntegerType())
df.where(size_(col("tokens")) <= 3).show()
## +---------+
## | tokens|
## +---------+
## |[S, U, S]|
## +---------+
如果您使用HiveContext
,那么size
UDF 与原始 SQL 应该适用于任何版本:
df.registerTempTable("df")
sqlContext.sql("SELECT * FROM df WHERE size(tokens) <= 3").show()
## +--------------------+
## | tokens|
## +--------------------+
## |ArrayBuffer(S, U, S)|
## +--------------------+
对于字符串列,您可以使用上面定义的udf
或length
函数:
from pyspark.sql.functions import length
df = sqlContext.createDataFrame([("fooo", ), ("bar", )], ("k", ))
df.where(length(col("k")) <= 3).show()
## +---+
## | k|
## +---+
## |bar|
## +---+
【讨论】:
如果列是string
并且我假装按string
的长度进行过滤,那该怎么办?
同一个udf或者length
函数。【参考方案2】:
以下是 scala 中字符串的示例:
val stringData = Seq(("Maheswara"), ("Mokshith"))
val df = sc.parallelize(stringData).toDF
df.where((length($"value")) <= 8).show
+--------+
| value|
+--------+
|Mokshith|
+--------+
df.withColumn("length", length($"value")).show
+---------+------+
| value|length|
+---------+------+
|Maheswara| 9|
| Mokshith| 8|
+---------+------+
【讨论】:
我的问题有所不同,我指的是一个字符串数组的列。【参考方案3】:@AlbertoBonsanto:下面的代码过滤器基于数组大小:
val input = Seq(("a1,a2,a3,a4,a5"), ("a1,a2,a3,a4"), ("a1,a2,a3"), ("a1,a2"), ("a1"))
val df = sc.parallelize(input).toDF("tokens")
val tokensArrayDf = df.withColumn("tokens", split($"tokens", ","))
tokensArrayDf.show
+--------------------+
| tokens|
+--------------------+
|[a1, a2, a3, a4, a5]|
| [a1, a2, a3, a4]|
| [a1, a2, a3]|
| [a1, a2]|
| [a1]|
+--------------------+
tokensArrayDf.filter(size($"tokens") > 3).show
+--------------------+
| tokens|
+--------------------+
|[a1, a2, a3, a4, a5]|
| [a1, a2, a3, a4]|
+--------------------+
【讨论】:
以上是关于使用列的长度过滤 DataFrame的主要内容,如果未能解决你的问题,请参考以下文章