Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/apache-spark/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Apache spark 使用pyspark将函数应用于groupBy数据_Apache Spark_Pyspark - Fatal编程技术网

Apache spark 使用pyspark将函数应用于groupBy数据

Apache spark 使用pyspark将函数应用于groupBy数据,apache-spark,pyspark,Apache Spark,Pyspark,我试图在另一列上分组时从csv中获取字数。我的csv有三列:id、message和user_id。我在中阅读了这些内容,然后拆分消息并存储一个Unigram列表: +-----------------+--------------------+--------------------+ | id| message| user_id| +-----------------+--------------------+----

我试图在另一列上分组时从csv中获取字数。我的csv有三列:id、message和user_id。我在中阅读了这些内容,然后拆分消息并存储一个Unigram列表:

+-----------------+--------------------+--------------------+
|               id|             message|             user_id|
+-----------------+--------------------+--------------------+
|10100720363468236|[i'm, sad, to, mi...|dceafb541a1b8e894...|
|10100718944611636|[what, does, the,...|dceafb541a1b8e894...|
|10100718890699676|[at, the, oecd, w...|dceafb541a1b8e894...|
+-----------------+--------------------+--------------------+
接下来,给定我的数据帧
df
,我想按
user\u id
进行分组,然后获取每个单报的计数。作为简单的第一步,我尝试按
user\u id
分组,并获得分组消息字段的长度:

从集合导入计数器
从pyspark.sql.types导入ArrayType、StringType、IntegerType
从pyspark.sql.functions导入udf
df=self.session.read.csv(self.corptable,header=True,
mode=“dropmorformed”,)
#拆分我的邮件。。。。
#消息现在是ArrayType(StringType())
分组=df.groupBy(df[“用户id”])
计数器=udf(lambda l:len(l),数组类型(StringType())
agg(计数器(df[“message”]))
打印(grouped.collect())
我得到以下错误:

pyspark.sql.utils.AnalysisException: "expression '`message`' is neither present in the group by, nor is it an aggregate function. Add to group by or wrap in first() (or first_value) if you don't care which value you get.;"
不知道如何避免这个错误。通常,在对另一列进行分组时,如何将函数应用于一列?我是否总是必须创建用户定义的函数?非常新的火花

编辑:下面是我如何解决这个问题的,在一个单独的Python文件中给定一个标记器:

group\u field=“用户id”
message\u field=“message”
context=SparkContext()
会话=SparkSession\
建筑商先生\
.appName(“dlastk”)\
.getOrCreate()
#添加标记器
context.addPyFile(标记器路径)
从标记器导入标记器
标记器=标记器()
spark_tokenizer=udf(tokenizer.tokenize,ArrayType(StringType()))
df=session.read.csv(“myFile.csv”,header=True,)
df=df[组字段,消息字段]
#标记消息字段
df=df.withColumn(消息\字段,火花\标记器(df[消息\字段])
#从标记化消息创建ngram
n=1
grouped=df.rdd.map(lambda行:(行[0],计数器([“”.join(x)表示zip中的x(*[row[1][i:]表示范围(n)]))))))。reduceByKey(添加)
#展平rdd,使每行包含(组id、ngram、计数、相对频率
flat=grouped.flatMap(lambda行:[[row[0],x,y,y/sum(row[1].values())]用于第[1]行中的x,y.项())
#rdd->DF
flat=flat.toDF()
flat.write.csv(“myNewCSV.csv”)
数据如下所示:

# after read
+--------------------+--------------------+
|             user_id|             message|
+--------------------+--------------------+
|00035fb0dcfbeaa8b...|To the douchebag ...|
|00035fb0dcfbeaa8b...|   T minus 1 week...|
|00035fb0dcfbeaa8b...|Last full day of ...|
+--------------------+--------------------+

# after tokenize
+--------------------+--------------------+
|             user_id|             message|
+--------------------+--------------------+
|00035fb0dcfbeaa8b...|[to, the, doucheb...|
|00035fb0dcfbeaa8b...|[t, minus, 1, wee...|
|00035fb0dcfbeaa8b...|[last, full, day,...|
+--------------------+--------------------+

# grouped: after 1grams extracted and Counters added
[('00035fb0dcfbeaa8bb70ffe24d614d4dcee446b803eb4063dccf14dd2a474611', Counter({'!': 545, '.': 373, 'the': 306, '"': 225, ...

# flat: after calculating sum and relative frequency for each 1gram
[['00035fb0dcfbeaa8bb70ffe24d614d4dcee446b803eb4063dccf14dd2a474611', 'face', 3, 0.000320547066994337], ['00035fb0dcfbeaa8bb70ffe24d614d4dcee446b803eb4063dccf14dd2a474611', 'was', 26, 0.002778074580617587] ....

# after flat RDD to DF
+--------------------+---------+---+--------------------+
|                  _1|       _2| _3|                  _4|
+--------------------+---------+---+--------------------+
|00035fb0dcfbeaa8b...|     face|  3| 3.20547066994337E-4|
|00035fb0dcfbeaa8b...|      was| 26|0.002778074580617587|
|00035fb0dcfbeaa8b...|      how| 22|0.002350678491291...|
+--------------------+---------+---+--------------------+
尝试:

从pyspark.sql.functions导入*
df.withColumn(“单词”,explode(“消息”))\
.groupBy(“用户id”、“单词”).count()\
.groupBy(“用户id”)\
.agg(收集列表(结构(“单词”、“计数”))

一种自然的方法是将单词分组到一个列表中,然后使用python函数
Counter()
生成单词计数。对于这两个步骤,我们都将使用
udf
。首先,一种方法将平展由多个数组的
collect\u list()
生成的嵌套列表:

unpack\u udf=udf(
lambda l:[子列表中的项目在l中,子列表中的项目在l中]
)
第二,生成单词计数元组的元组,或者在我们的例子中是
struct

从pyspark.sql.types导入*
从收款进口柜台
#我们需要指定返回对象的模式
schema_count=ArrayType(StructType([
StructField(“word”,StringType(),False),
StructField(“count”,IntegerType(),False)
]))
计数\自定义项=自定义项(
lambda s:计数器。最常见(),
模式计数
)
总而言之:

从pyspark.sql.functions导入收集列表
(df.groupBy(“id”)
.agg(收集列表(“消息”)。别名(“消息”))
.withColumn(“消息”,解包自定义项(“消息”))
.withColumn(“message”,count_udf(“message”)).show(truncate=False)
+-----------------+------------------------------------------------------+
|id |消息|
+-----------------+------------------------------------------------------+
|10100718890699676 |[[oecd,1],[the,1],[with,1],[at,1]]|
|10100720363468236[what,3],[me,1],[sad,1],[to,1],[does,1],[the,1]]|
+-----------------+------------------------------------------------------+
数据:

df=sc.parallelize([(10100720363468236,[“what”,“sad”,“to”,“me]),
(10100720363468236,[“what”,“what”,“does”,“the”]),
(10100718890699676,[“at”,“the”,“oecd”,“with”]))))。toDF([“id”,“message”])

Nice,似乎与我昨晚想到的类似。我想知道哪一个更有效?您可以尝试使用
time
包来测量执行时间。在代码块的开头:
start\u time=time.time()
,结尾:
打印(“执行时间--%s秒--%(time.time()-start\u time))