在pyspark数据框中显示不同的列值

214
使用pyspark dataframe,如何执行与Pandas中的df ['col'] .unique()等效的操作?
我想列出pyspark dataframe列中所有唯一的值。
不使用SQL(注册模板,然后对不同值进行SQL查询)。
也不需要groupby然后使用countDistinct,相反,我想检查该列中的唯一值。
15个回答

392

这应该有助于获取列的不同值:

df.select('column1').distinct().collect()
请注意,.collect()没有内置的返回值数量限制,因此这可能会很慢--请改用.show()或在.collect()之前添加.limit(20)来管理它。

此代码返回的数据不可迭代,即我能看到不同的数据位但无法在代码中进行迭代。是否有其他方法可以实现。我尝试使用toPandas()将其转换为Pandas df,然后获取具有唯一值的可迭代对象。然而,遇到“找不到Pandas”错误信息。 - Abhi
12
@Abhi:不要使用.show(),而要使用.collect(),这样你将获得该特定列所有不同值的迭代器。但是请确保您的主节点有足够的内存来保持这些唯一值,因为.collect()将把所请求的所有数据(在本例中,是该列的唯一值)推送到主节点 :) - Satya
3
要获取Python中实际值而不是Row对象的列表,您需要使用类似于此答案中的列表推导式:https://dev59.com/EFkS5IYBdhLWcg3w25sM#60896261 - Ric S
df.select('column').distinct().collect().toPandas().column.to_list() - travelingbones
2
pyspark_df.select(target_column_name).distinct().toPandas()[target_column_name].to_list() 将返回一个扁平的 Python 列表。 - Bikash Gyawali
如果你不想使用pandas,你也可以使用一个flat map函数将其转换为Python的平面列表:pyspark_df.select(target_column_name).distinct().rdd.flatMap(list).collect() - undefined

126
假设我们正在使用以下数据表示(两列,k和v,其中k包含三个条目,两个是唯一的:
+---+---+
|  k|  v|
+---+---+
|foo|  1|
|bar|  2|
|foo|  3|
+---+---+

使用Pandas数据框:
import pandas as pd
p_df = pd.DataFrame([("foo", 1), ("bar", 2), ("foo", 3)], columns=("k", "v"))
p_df['k'].unique()

这将返回一个`ndarray`,即`array(['foo', 'bar'], dtype=object)`。
你要求一个“pyspark dataframe替代pandas df['col'].unique()”。现在,给定以下Spark dataframe:
s_df = sqlContext.createDataFrame([("foo", 1), ("bar", 2), ("foo", 3)], ('k', 'v'))

如果你想要从Spark得到相同的结果,也就是一个ndarray,请使用toPandas()函数。
s_df.toPandas()['k'].unique()

或者,如果您不需要特定的ndarray,并且只想要列k的唯一值列表:
s_df.select('k').distinct().rdd.map(lambda r: r[0]).collect()

最后,你还可以使用列表推导式如下所示:
[i for i in s_df.select('k').distinct().collect()]

2
嗨,Eddies,最后一行代码distinct().map()对我没用。错误:AttributeError: 'DataFrame'对象没有'map'属性。我使用的是Spark 2.0。至于toPandas,我不会说它是一个替代方法,因为它首先将Spark DataFrame转换为Pandas DataFrame,然后在其上执行Pandas操作。 - Satya
2
嗨,萨蒂亚。我刚刚更新了答案,在distinct()之后添加了一个.rdd调用。在Spark 1.6.2中没有这个也可以工作,但我刚刚确认编辑后的答案在Spark 2.0.0中也可以工作。 - eddies
7
为什么要通过将Spark DataFrame转换为Pandas DataFrame(如果数据量巨大,则会受到伤害)或利用RDD操作来避免Spark DataFrame操作,当Spark DataFrame完全能够胜任此任务?请参见@Pabbati的回答。 - Laurens Koppenol
2
是的,问题标题包含“显示”一词。但是发帖人明确澄清,仅仅看到结果是不够的,他想要一个列表。如上所述,请查看发帖人对seufagner答案的评论。 - eddies
好主意。我建议对问题进行编辑,请求列出列表而不是显示结果。 - RNHTTR
显示剩余3条评论

25
您可以使用df.dropDuplicates(['col1', 'col2'])来获取仅基于数组中的colX的唯一行。

3
@seufagner-是的,我可以使用df.dropDuplictes(['col1'])来查看(标记为SEE)唯一值,但是如果没有collect(to_rdd或to pandas DF然后df['col'].unique()),我无法获取唯一值列表。感谢建议。 - Satya
用户并没有询问如何显示非重复值。他只是想要获取所有唯一/不同的项目列表,其中包括重复项! - Utsav Jha
这是正确的,因为df.select(<column name>).collect()是一项昂贵的操作,可能会导致阶段失败错误。 - Palash Mondal

20
如果您想查看数据框中特定列的不同值,只需编写以下代码即可。它将显示 df 数据框中 colname 列的100个不同值(如果有100个可用值)。
df.select('colname').distinct().show(100, False)

如果你想在不同的值上做一些花哨的事情,可以将这些不同的值保存在一个向量中:

即可。

a = df.select('colname').distinct()

14

collect_set 可以帮助从给定的 pyspark.sql.DataFrame 列中获取唯一值:

df.select(F.collect_set("column").alias("column")).first()["column"]

3
我同意使用collect_set,但我认为以下代码会更简洁:df.agg(F.collect_set("column")).collect()[0][0] - stinodego

12

你可以做到

distinct_column = 'somecol' 

distinct_column_vals = df.select(distinct_column).distinct().collect()
distinct_column_vals = [v[distinct_column] for v in distinct_column_vals]

这非常简单,谢谢。 - GenDemo
只是一个快速的评论:由于您已经在第一行中选择了distinct_column,所以下面不需要重复。您可以直接使用[v[0] for v in distinct_column_vals] - Ric S

4
与其他答案类似,但问题似乎不希望返回行对象,而是实际值。
理想的一行代码是 df.select('column').distinct().collect().toPandas().column.to_list() 假设运行.collect()不会占用太多内存。
我建议先使用df.select('column')。distinct().count()来估计大小,并确保它事先不会太大。

3
如果你想从一个数据框(df)中选择所有的列并使它们不重复,那么请使用以下代码:df.select('*').distinct().show(10,truncate=False)

3
除了 dropDuplicates 选项之外,还有一个方法,正如我们在 pandas 中所知道的那样,名为 drop_duplicates:

drop_duplicates()dropDuplicates() 的别名。

示例
s_df = sqlContext.createDataFrame([("foo", 1),
                                   ("foo", 1),
                                   ("bar", 2),
                                   ("foo", 3)], ('k', 'v'))
s_df.show()

+---+---+
|  k|  v|
+---+---+
|foo|  1|
|foo|  1|
|bar|  2|
|foo|  3|
+---+---+

子集合并

s_df.drop_duplicates(subset = ['k']).show()

+---+---+
|  k|  v|
+---+---+
|bar|  2|
|foo|  1|
+---+---+
s_df.drop_duplicates().show()


+---+---+
|  k|  v|
+---+---+
|bar|  2|
|foo|  3|
|foo|  1|
+---+---+

2

先运行这个

df.createOrReplaceTempView('df')

然后运行。
spark.sql("""
    SELECT distinct
        column name
    FROM
        df
    """).show()

查询不使用SQL语法在pyspark中。要求使用纯粹的pyspark方法进行去重。 - Chandra

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接