pyspark中是否可以计算唯一值

时间:2019-11-08 18:59:04

标签: dataframe apache-spark pyspark apache-spark-sql

我有一个spark数据帧(12m x 132),我试图按列计算唯一值的数量,并删除只有1个唯一值的列。

到目前为止,我已经像这样使用了pandas nunique函数:

import pandas as pd

df = sql_dw.read_table(<table>)
df_p = df.toPandas()

nun = df_p.nunique(axis=0)
nundf = pd.DataFrame({'atr':nun.index, 'countU':nun.values})

dropped = []
for i, j in nundf.values:
  if j == 1:
    dropped.append(i)
    df = df.drop(i)
print(dropped)

有没有办法做到更自然地产生火花-即不使用熊猫?

3 个答案:

答案 0 :(得分:2)

我很抱歉,因为我在pyspark中没有解决方案,但纯粹是火花,在您找不到pyspark方式的情况下,它可以转让或使用。

您可以创建一个空白列表,然后使用foreach,检查哪些列的唯一计数为1,然后将其追加到空白列表。

从那里,您可以将列表用作过滤器,并从数据框中删除这些列。

    var list_of_columns: List[String] = ()

    df_p.columns.foreach{c => 
      if (df_p.select(c).distinct.count == 1)
         list_of_columns ++= List(c)

    df_p_new = df_p.drop(list_of_columns:_*)


答案 1 :(得分:1)

请查看下面的注释示例。该解决方案需要更多的python作为pyspark的专门知识。

import pyspark.sql.functions as F
#creating a dataframe
columns = ['asin' ,'ctx' ,'fo' ]

l = [('ASIN1','CTX1','FO1')
,('ASIN1','CTX1','FO1')
,('ASIN1','CTX1','FO2')
,('ASIN1','CTX2','FO1')
,('ASIN1','CTX2','FO2')
,('ASIN1','CTX2','FO2')
,('ASIN1','CTX2','FO3')
,('ASIN1','CTX3','FO1')
,('ASIN1','CTX3','FO3')]

df=spark.createDataFrame(l, columns)

df.show()
#we create a list of functions we want to apply
#in this case countDistinct for each column
expr = [F.countDistinct(c).alias(c) for c in df.columns]

#we apply those functions
countdf =  df.select(*expr)
#this df has just one row
countdf.show()

#we extract the columns which have just one value
cols2drop = [k for k,v in countdf.collect()[0].asDict().items() if v == 1]
df.drop(*cols2drop).show()

输出:

+-----+----+---+
| asin| ctx| fo|
+-----+----+---+
|ASIN1|CTX1|FO1|
|ASIN1|CTX1|FO1|
|ASIN1|CTX1|FO2|
|ASIN1|CTX2|FO1|
|ASIN1|CTX2|FO2|
|ASIN1|CTX2|FO2|
|ASIN1|CTX2|FO3|
|ASIN1|CTX3|FO1|
|ASIN1|CTX3|FO3|
+-----+----+---+

+----+---+---+
|asin|ctx| fo|
+----+---+---+
|   1|  3|  3|
+----+---+---+

+----+---+
| ctx| fo|
+----+---+
|CTX1|FO1|
|CTX1|FO1|
|CTX1|FO2|
|CTX2|FO1|
|CTX2|FO2|
|CTX2|FO2|
|CTX2|FO3|
|CTX3|FO1|
|CTX3|FO3|
+----+---+

答案 2 :(得分:0)

您可以按该列将df分组,并计算该列的不同值:

df = df.groupBy("column_name").agg(countDistinct("column_name").alias("distinct_count"))

然后按具有超过1个distinct_count的行过滤df:

df = df.filter(df.distinct_count > 1)