我有一个包含以下列的DataFrame。
scala> show_times.printSchema
root
|-- account: string (nullable = true)
|-- channel: string (nullable = true)
|-- show_name: string (nullable = true)
|-- total_time_watched: integer (nullable = true)
这是关于客户观看特定节目的次数的数据。我应该根据观看的总时间对每个节目的客户进行分类。
数据集总共有1.33亿行,其中192个不同show_names
。
对于每个个人节目,我应该将客户分为3类(1,2,3)。
我使用Spark MLlib的QuantileDiscretizer
目前,我循环播放每个节目并按顺序方式运行QuantileDiscretizer
,如下面的代码所示。
我最终想要的是以下样本输入来获取样本输出。
示例输入:
account,channel,show_name,total_time_watched
acct1,ESPN,show1,200
acct2,ESPN,show1,250
acct3,ESPN,show1,800
acct4,ESPN,show1,850
acct5,ESPN,show1,1300
acct6,ESPN,show1,1320
acct1,ESPN,show2,200
acct2,ESPN,show2,250
acct3,ESPN,show2,800
acct4,ESPN,show2,850
acct5,ESPN,show2,1300
acct6,ESPN,show2,1320
示例输出:
account,channel,show_name,total_time_watched,Time_watched_bin
acct1,ESPN,show1,200,1
acct2,ESPN,show1,250,1
acct3,ESPN,show1,800,2
acct4,ESPN,show1,850,2
acct5,ESPN,show1,1300,3
acct6,ESPN,show1,1320,3
acct1,ESPN,show2,200,1
acct2,ESPN,show2,250,1
acct3,ESPN,show2,800,2
acct4,ESPN,show2,850,2
acct5,ESPN,show2,1300,3
acct6,ESPN,show2,1320,3
是否有一种更高效,更分散的方式来使用某些groupBy
- 类似的操作,而不是循环遍历每个show_name
并将其一个接一个地捆绑?
答案 0 :(得分:0)
我对QuantileDiscretizer
一无所知,但认为您最关心的是应用QuantileDiscretizer
的数据集。我想你想弄清楚如何将输入数据集拆分成每个show_name
的较小数据集(你说输入数据集中有192个不同的show_name
)。
我注意到您使用镶木地板作为输入格式。我对格式的理解非常有限但是我注意到人们正在使用一些分区方案将大数据集拆分成更小的块,然后他们就可以处理他们喜欢的任何内容(按照某些分区方案)。
在您的情况下,分区方案可以包括show_name
。
这会使你的案件变得微不足道,因为分裂是在写作时完成的(又名不再是我的问题)。
请参阅How to save a partitioned parquet file in Spark 2.1?
根据您的迭代解决方案,您可以将每次迭代包装到您要提交以并行处理的Future。
Spark SQL' SparkSession(和Spark Core' s SparkContext)是线程安全的。
filter
和union
运营商在遵循这个解决方案之前我会三思而行,因为它会给你的肩膀增加负担,我认为可以通过解决方案1轻松解决。
鉴于您已经获得了一个大的1.33亿行拼花文件,我首先使用show_name
运算符按filter
构建192个数据集(正如您构建{ {1}}这是违反名称的,因为它是show_rdd
而非DataFrame
)和RDD
(再次与您一样)。
请参阅Dataset API。
我认为这可以起作用,但我自己也没有检查过。
您可以使用窗口函数(请参阅WindowSpec和列的over运算符)。
窗口函数会为您提供分区(窗口),而union
以某种方式将over
应用于窗口/分区。然而,这将需要"解构" QuantileDiscretizer
进入QuantileDiscretizer
训练模型,以某种方式再次将结果模型拟合到窗口。
我认为这是可行的,但我自己并没有这样做。遗憾。
答案 1 :(得分:-1)
这是一个较早的问题。但是,回答该问题将有助于将来遇到相同情况的人。
可以使用熊猫udf函数来实现。熊猫UDF函数的输入和输出都是数据帧。我们需要提供输出数据帧的架构,如下面的代码示例中的注释所示。下面的代码示例可以达到所需的结果。
output_schema = StructType(df.schema.fields + [StructField('Time_watched_bin', IntegerType(), True)])
@pandas_udf(output_schema, PandasUDFType.GROUPED_MAP)
# pdf: pandas dataframe
def get_buckets(pdf):
pdf['Time_watched_bin'] = pd.cut(pdf['total_time_watched'], 3, labels=False)
return pdf
df = df.groupby('show_name').apply(get_buckets)
df将具有带有存储桶信息的新列“ Time_watched_bin”。