我有一种情况,我的数据框有3列a,b和c。我需要验证所有列的长度是否等于100。基于验证,我正在创建状态列,如a_status,b_status,c_status,其值分别为5(成功)和10(失败)。在“失败”方案中,我需要更新计数并创建新的列a_sample,b_sample,c_sample,并用“,”分隔约5个失败样本值。对于创建示例列,我尝试过
df= df.select(df.columns.toList.map(col(_)) :::
df.columns.toList.map( x => (lit(getSample(df.select(x, x + "_status").filter(x + "_status=10" ).select(x).take(5))).alias(x + "_sample")) ).toList: _* )
getSample方法将仅获取行数组并将其连接为字符串。对于有限的列和数据大小,这很好用。但是,如果列数> 200并且数据> 100万行,则会对性能产生巨大影响。有其他替代方法吗?
答案 0 :(得分:0)
问题陈述的细节不清楚时,您可以将任务分为两部分:
“行类型”的行业术语是地层/地层,而方法(2)是通过分层抽样而无需收集数据给驱动程序(数据大时您不想这样做), Spark是通过df.stat.sampleBy()
实现的。作为一种统计功能,它不适用于确切的行号,而只能用于分数。如果您绝对必须获得具有确切行数的样本,则有两种策略:
row_number()
窗口函数,然后过滤器'row_num < n
。firstN(col, n)
。这将更快,但需要做更多的工作。参见https://docs.databricks.com/spark/latest/spark-sql/udaf-scala.html 用例的另一个挑战是您希望按列完成此操作。这不适用于Spark的转换,例如分组或sampleBy
,它们在行上进行操作。一种简单的方法是一次遍历几次数据。如果您绝对必须在一次传递数据中执行此操作,则需要构建更多自定义的UDAF或Aggregator
,例如,等效于takeFirstNFromAWhereBHasValueC(n, colA, colB, c)
。