【发布时间】:2019-09-03 02:52:12
【问题描述】:
我需要一种有效的方法来列出和删除 Spark DataFrame 中的一元列(我使用 PySpark API)。我将一元列定义为最多具有一个不同值的列,出于定义的目的,我也将null 计为一个值。这意味着在某些行中具有不同 non-null 值而在其他行中具有不同 null 值的列不是一元列。
根据this question 的答案,我设法编写了一种有效的方法来获取空列列表(它们是我的一元列的子集)并将它们删除,如下所示:
counts = df.summary("count").collect()[0].asDict()
null_cols = [c for c in counts.keys() if counts[c] == '0']
df2 = df.drop(*null_cols)
基于我对 Spark 内部工作原理的非常有限的理解,这很快,因为方法摘要同时操作整个数据帧(我的初始数据帧中大约有 300 列)。不幸的是,我找不到类似的方法来处理第二种类型的一元列——那些没有null 值但为lit(something) 的列。
我目前拥有的是这个(使用我从上面的代码 sn-p 获得的df2):
prox_counts = (df2.agg(*(F.approx_count_distinct(F.col(c)).alias(c)
for c in df2.columns
)
)
.collect()[0].asDict()
)
poss_unarcols = [k for k in prox_counts.keys() if prox_counts[k] < 3]
unar_cols = [c for c in poss_unarcols if df2.select(c).distinct().count() < 2]
基本上,我首先以快速但近似的方式找到可能是一元的列,然后更详细、更缓慢地查看“候选”。
我不喜欢它的是 a) 即使进行了近似的预选,它仍然相当慢,即使此时我只有大约 70 列(大约 600 万列)也需要一分钟多的时间才能运行行)和b)我使用approx_count_distinct和神奇的常数3(approx_count_distinct不算null,因此3而不是2)。由于我不确定approx_count_distinct 在内部是如何工作的,我有点担心3 不是一个特别好的常数,因为该函数可能会估计不同(non-null)值的数量,比如5是 1,因此可能需要更高的常数来保证候选列表 poss_unarcols 中没有任何遗漏。
有没有更聪明的方法来做到这一点,理想情况下,我什至不必单独删除空列并一口气完成所有操作(尽管这实际上非常快,所以这是一个大问题) ?
【问题讨论】:
标签: python apache-spark dataframe pyspark