【问题标题】:Pyspark - hive dataframe sort by two columns breaks the dataframePyspark - 按两列排序的 Hive 数据框破坏了数据框
【发布时间】:2022-01-01 19:15:08
【问题描述】:

我在从 hdfs hive 上下文中排序数据帧时遇到问题。 尝试对结构类似的数据框进行排序:

+---+--------------+---------------+
| id|parameter_name|parameter_value
+---+--------------+---------------+
|id1|    name_en   |    value a
|id1|    name_il   |    value b
|id1|    address_en|    value c
|id1|    address_il|    value d
|id2|    name_il   |    value f
|id2|    name_en   |    value e
|id2|    address_il|    value h
|id1|    address_en|    value g
+---+--------------+---------------+

我正在尝试以对 id 进行排序的方式对这个数据框进行排序,并且每个 id 的 df 中的 parameter_name 序列如下:

name_en
name_il
address_en
address_il

请注意,在示例中并非如此,并且 id 之间的名称和地址是翻转的。

尝试使用 df.sort(["id","parameter_name"]) 会产生混合结果,进一步混合数据帧并将 id 拆分为:

id1, name_en
id1, name_il
id2, name_il
id2, name_en
id1, address_en
id1, address_il
id2, address_il
id2, address_en

【问题讨论】:

  • 我在做df.sort(["id","parameter_name"])时没有得到相同的结果。
  • 这是一个简化的例子。实际的数据框在一个蜂巢中并且更大。本质上,当按多列排序时,它按第一个元素对 df 进行排序,然后将每个已排序组中的任何未排序元素也固定为要排序的。这在我的情况下中断,我试图了解是否有解决方法
  • 你是什么意思“打破”?它失败并出现错误?什么错误?
  • 不,没有错误。返回的表未排序。而不是 id1, name_en id1, name_il id1, address_en id1, address_il id2, name_en id2, name_il id2, address_en id2, address_il 以它返回的所需方式排序: id1, name_en id1, name_il id2, name_il id2, name_en id1, address_en id1, address_il id2, address_il id2, address_en
  • 你会df.sort(...); df.show() 吗?或df.sort(...).show() ?或df = df.sort(...); df.show() ?sort 是一个转换,它返回一个数据帧。如果要在执行操作 showwrite 之前保存转换,则需要将此数据帧分配回 df

标签: python dataframe sorting pyspark hive


【解决方案1】:

我创建了您的数据框,但为 parameter_value 分配了随机值,因此订单不再相关。

from random import random

data = [
    {"id": "id1", "parameter_name": "name_en", "parameter_value": random()},
    {"id": "id1", "parameter_name": "name_il", "parameter_value": random()},
    {"id": "id1", "parameter_name": "address_en", "parameter_value": random()},
    {"id": "id1", "parameter_name": "address_il", "parameter_value": random()},
    {"id": "id2", "parameter_name": "name_il", "parameter_value": random()},
    {"id": "id2", "parameter_name": "name_en", "parameter_value": random()},
    {"id": "id2", "parameter_name": "address_il", "parameter_value": random()},
    {"id": "id2", "parameter_name": "address_en", "parameter_value": random()},
]
df = spark.createDataFrame(data)

df.show()
+---+--------------+-------------------+                                        
| id|parameter_name|    parameter_value|
+---+--------------+-------------------+
|id1|    address_il|0.11850447351294957|
|id2|       name_en|0.18902815459657452|
|id2|    address_il|  0.294998203578158|
|id1|    address_en|0.48741740190944827|
|id2|       name_il| 0.5651073044407224|
|id2|    address_en| 0.6530661784882391|
|id1|       name_il| 0.6797674631659714|
|id1|       name_en| 0.9887386653580036|
+---+--------------+-------------------+

那么,我需要创建一个排序列来维护您需要的人工排序:

from pyspark.sql import functions as F

ordering_col = (
    F.when(F.col("parameter_name") == "name_en", 1)
    .when(F.col("parameter_name") == "name_il", 2)
    .when(F.col("parameter_name") == "address_en", 3)
    .when(F.col("parameter_name") == "address_il", 4)
)

df.orderBy("id", ordering_col).show()
+---+--------------+-------------------+
| id|parameter_name|    parameter_value|
+---+--------------+-------------------+
|id1|       name_en| 0.9887386653580036|
|id1|       name_il| 0.6797674631659714|
|id1|    address_en|0.48741740190944827|
|id1|    address_il|0.11850447351294957|
|id2|       name_en|0.18902815459657452|
|id2|       name_il| 0.5651073044407224|
|id2|    address_en| 0.6530661784882391|
|id2|    address_il|  0.294998203578158|
+---+--------------+-------------------+

【讨论】:

  • 不错!我完全搞砸了这个:'D
  • 我现在就试试这个。据我所知,不需要任何东西来保持人为的顺序,因为 parameter_name 是一个字符串,并且可以这样排序。在您的情况下,我还需要为 id 创建一个人工顺序,因为它不是整数。会尽快通知您
  • @xMustangLovesPie 好吧,字母顺序是 address_en, address_il, name_en, name_il(或相反 - 向后阅读 - 如果您订购 desc)。所以,你需要人工排序。
  • 我应该指出我的订单的重点是它每次都重复并且不会在两者之间的某个地方混搭。无论如何,我尝试了您的解决方案,它可以在本地自定义数据框上运行。但是再一次,在配置单元上,它根本无法正确重建数据帧。它像这样在中间拆分它:
  • |id1|名称_zh| 0.9887| |id1|名称_il| 0.6797| |id2|name_zh |0.48741| |id2|name_il |0.11850| |id3| name_zh|0.18902| |id3|名称_il| 0.5651| |id1|address_en|0.18902| |id1|address_il| 0.5650| |id2|address_en| 0.6530| |id2|address_il| 0.294| |id3|address_en|0.18902| |id3|address_il| 0.5651| +---+--------------+-------+` 如你所见,id 是分开的..
【解决方案2】:

只需将 Pyspark 数据帧转换为 Pandas 数据帧并执行排序操作。您可以使用 sparkContext.createDataFrame(panda_df) 将数据帧转换回来,如下所示:

panda_df = dataframe.toPandas().sort_values(["id", "parameter_name"], ascending=(True, False))
sorted_df = sparkContext.createDataFrame(panda_df)
sorted_df.show()

【讨论】:

  • 如果你的数据适合内存,那么就使用 Pandas。当数据太大而无法容纳内存时,您应该使用 spark。
猜你喜欢
  • 2017-04-30
  • 2018-10-05
  • 1970-01-01
  • 2018-07-11
  • 2022-11-13
  • 2020-05-15
  • 2019-03-07
  • 1970-01-01
  • 2017-06-28
相关资源
最近更新 更多