如何检查 pyspark dataframe 中的字符串列是否全为数字

21

我有一个PySpark Dataframe,其中包含一列字符串。如何检查其中的哪些行是数字。 我在PySpark的官方文档中找不到任何函数。

values = [('25q36',),('75647',),('13864',),('8758K',),('07645',)]
df = sqlContext.createDataFrame(values,['ID',])
df.show()
+-----+
|   ID|
+-----+
|25q36|
|75647|
|13864|
|8758K|
|07645|
+-----+
在Python中,有一个函数.isDigit()用于判断string是否只包含数字,返回TrueFalse
期望的数据框如下:
+-----+-------+
|   ID| Value |
+-----+-------+
|25q36| False |
|75647| True  |
|13864| True  |
|8758K| False |
|07645| True  |
+-----+-------+

我希望避免创建一个UDF

7个回答

29

一个简单的投掷就能完成任务:

from pyspark.sql import functions as F

my_df.select(
  "ID",
  F.col("ID").cast("int").isNotNull().alias("Value ")
).show()

+-----+------+
|   ID|Value |
+-----+------+
|25q36| false|
|75647|  true|
|13864|  true|
|8758K| false|
|07645|  true|
+-----+------+

谢谢Steven。这肯定管用。我以为也许有内置函数。如果我找不到一个,我将点击这个作为答案。 - cph_sto
注意!由于整数范围为-2,147,483,647到+2,147,483,647,最好使用“long”而不是“int”。 - Mohammad-Reza Malekpour

5

使用正则表达式进行过滤

虽然我很欣赏 Steven 提供的创意解决方案,但是这里有一个更加简单的建议:

df.filter(~df.ID.rlike('\D+')).show()

首先,使用rlike('\D+')选择每一行中包含非数字字符的行,然后在筛选条件的开头使用~排除这些行。


OP 希望添加一列,而不是过滤器。 - Steven

5
我同意@steven的回答,但是我想对其进行轻微修改,因为我希望整个表格都被过滤掉。 请参阅下文。
df2.filter(F.col("id").cast("int").isNotNull()).show()

另外,无需创建名为Values的新列。


与上述类似的替代解决方案是 -

display(df2.filter(f"CAST({'id'} as INT) IS NOT NULL")

OP想要一个新的列,而不是一个过滤器。 - Steven

2

搜索非数字行的最清晰的方法可能是这样的:

from pyspark.sql import functions as F

df.select("col_a",F.regexp_replace(col("col_a"), "[^0-9]", "").alias("numeric"))\
    .filter(col("col_a")!=col("numeric"))\
    .distinct()\
    .show()

OP想要一个新的列,而不是一个过滤器。 - Steven

1

如果您愿意,您也可以构建一个定制的udf来实现此目的:

from pyspark.sql.types import BooleanType
from pyspark.sql import functions as F

def is_digit(val):
    if val:
        return val.isdigit()
    else:
        return False

is_digit_udf = udf(is_digit, BooleanType())

df = df.withColumn('Value', F.when(is_digit_udf(F.col('ID')), F.lit(True)).otherwise(F.lit(False)))

OP特别要求不使用UDF。 - Steven

1
df=spark.read.option("header", "true").csv("source_table.csv")
df=df.withColumn("is_valid",lit("true"))
df.withColumn("is_valid",when(col("age").cast("int").isNotNull(),col("is_valid")).otherwise("false")).show()  # this will work 
#if you want to use rlike this will work
pattern="^[0-9]*$"
source_df=df.withColumn("is_valid",
               when(col("age").rlike(pattern), col("is_valid")).otherwise("false"))

非常好,因为您避免使用了UDF函数。 - Artemination

0

试试这个,是Scala语言

spark.udf.register("IsNumeric", (inpColumn: Int) => BigInt(inpColumn).isInstanceOf[BigInt])
spark.sql(s""" select "ABCD", IsNumeric(1234) as IsNumeric_1  """).show(false)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接