Pyspark:TypeError:%d格式:需要数字,而不是列

时间:2018-07-14 19:37:34

标签: python apache-spark pyspark apache-spark-dataset

编辑:我不认为它是重复的,因为我不是在尝试在数据帧中合并数据,而是要获取int(或字符串)值以字符串格式使用它。用concat_ws处理的简单串联无法解决问题,因为“ 96-3-12”不会被解释为日期。我必须将其转换为1996-03-12或获取int值,以将其传递给datetime.date函数,然后应用datefiff函数。

我正在尝试在pyspark中查询数据集,并从出生月份和出生年份计算出近似年龄

from pyspark.sql.types import IntegerType
presc_par_med = med.join(presc.groupBy(presc.chaiprat).agg(F.sum(presc.nbmol).alias("nb_mol"), \
                                              F.count(presc.nbmol).alias("nb_presc"), \
                                              F.countDistinct(presc.numano).alias("nb_pat"), \
                                              F.datediff(F.current_date(), "%d-%d-15" % (med.year.cast(IntegerType()), med.month.cast(IntegerType()))).alias("age")), \
                     med.pranum == presc.chaiprat)

但是当我执行此操作时,我有一个错误

TypeError: %d format: a number is required, not Column

这不是演员的角色吗? 我尝试了%s,却遇到了另一个错误。

编辑:不同尝试,考虑答案和评论(并修改原始的查询,但无论如何还是错误的):

1。尝试使用concat_ws函数计算出生日期。

presc_par_med = med.withColumn("age", F.datediff(F.current_date(), \
                                F.concat_ws("-", med.year, med.month, F.lit("15")))) \
                   .withColumn("birthdate", F.concat_ws("-", med.year, med.month, F.lit("15"))) \
                   .join(presc.groupBy(presc.chaiprat) \
                              .agg(F.sum(presc.nbmol).alias("nb_mol"), \
                                   F.count(presc.nbmol).alias("nb_presc"), \
                                   F.countDistinct(presc.numano).alias("nb_pat")), \
                            med.pranum == presc.chaiprat)

输出为我们提供了

[Row(id=94, year=52, month=3, [...], age=None, birthdate=u'52-3-15', [...], nb_mol=14514, nb_presc=3624, nb_pat=520)]

日期已正确连接,但由于格式错误,年龄为“无”。 当我尝试修改年份和月份以完成世纪和.zfill(2)时,我遇到了与以前相同的问题:我无法达到任何整数或字符串值...

2。尝试使用生日日期功能以获取正确的日期

from pyspark.sql.types import IntegerType
from pyspark.sql.functions import udf
import datetime

@udf("date")
def birthdate(year, month, day):
    return datetime.date(year, month, day)

presc_par_med = med.withColumn("age", F.datediff(F.current_date(), \
                                F.concat_ws("-", med.year, med.month, F.lit("15")))) \
                   .withColumn("birthdate", birthdate(med.year.cast("int"), med.month.cast("int"), 15)) \
                   .join(presc.groupBy(presc.chaiprat) \
                              .agg(F.sum(presc.nbmol).alias("nb_mol"), \
                                   F.count(presc.nbmol).alias("nb_presc"), \
                                   F.countDistinct(presc.numano).alias("nb_pat")), \
                            med.pranum == presc.chaiprat)

我遇到了错误错误:

---> 12 presc_par_med = ...
[...]
Py4JError: An error occurred while calling z:org.apache.spark.sql.functions.col. Trace:
py4j.Py4JException: Method col([class java.lang.Integer]) does not exist
    at py4j.reflection.ReflectionEngine.getMethod(ReflectionEngine.java:318)
    at py4j.reflection.ReflectionEngine.getMethod(ReflectionEngine.java:339)

3。为功能点亮

from pyspark.sql.types import IntegerType
from pyspark.sql.functions import udf
import datetime

@udf("date")
def birthdate(year, month, day):
    return datetime.date(year, month, day)

presc_par_med = med.withColumn("age", F.datediff(F.current_date(), \
                                F.concat_ws("-", med.year, med.month, F.lit("15")))) \
                   .withColumn("birthdate", birthdate(med.year.cast("integer"), med.month.cast("integer"), F.lit(15))) \
                   .join(presc.groupBy(presc.chaiprat) \
                              .agg(F.sum(presc.nbmol).alias("nb_mol"), \
                                   F.countDistinct(presc.numano).alias("nb_pat")), \
                            med.pranum == presc.chaiprat)
presc_par_med.take(1)

错误:

Py4JJavaError: An error occurred while calling o2126.collectToPython.
: org.apache.spark.SparkException: Exception thrown in awaitResult: 
    at org.apache.spark.util.ThreadUtils$.awaitResult(ThreadUtils.scala:205)
[...]

  File "/usr/lib/spark/python/pyspark/worker.py", line 104, in <lambda>
    func = lambda _, it: map(mapper, it)
  File "<string>", line 1, in <lambda>
  File "/usr/lib/spark/python/pyspark/worker.py", line 69, in <lambda>
    return lambda *a: toInternal(f(*a))
  File "<ipython-input-90-1cbfa91d0947>", line 10, in datenaiss
TypeError: an integer is required

1 个答案:

答案 0 :(得分:1)

Column表达式表示逻辑执行计划而不是值的转换。强制转换没有什么不同-将一个表达式映射到另一个表达式。

要使用普通的Python函数对值进行运算,可以使用udf

from pyspark.sql.functions import udf

@udf("string")
def fifteenth(year, month):
    return "%d-%d-15" % (year, month)

import datetime

@udf("date")
def fifteenth(year, month):
    return datetime.date(year, month, 15)

并将其用作

F.datediff(
    F.current_date(), 
    fifteenth(med.year.cast("integer"), med.month.cast("integer"))
)

但是你真的不应该。最好:

from pyspark.sql.functions.import concat_ws, lit

concat_ws("-", med.year, med.month, lit("15"))