【问题标题】:PySpark: groupBy two columns with variables categorical and sort in ascending orderPySpark:groupBy 两列,变量分类并按升序排序
【发布时间】:2019-08-08 06:24:56
【问题描述】:

我是 Spark 的新手,我遇到了数据框的问题。我需要对两列(estado、producto)中的唯一分类变量进行分组,然后对第二列(producto)的唯一值进行计数和排序(asc)。我可以在 Pandas 中做到这一点,但我无法在 Spark 中重现它。

我的原始数据框是

+--------------------+--------------------+
|              estado|            producto|
+--------------------+--------------------+
|              MÉXICO|TINTE PARA EL CAB...|       
|              MÉXICO|         TELEVISORES|          
|              MÉXICO|              ACELGA|          
|              MÉXICO|       QUESO. COTIJA|          
|    DISTRITO FEDERAL|              AZUCAR|          
|              MÉXICO|      DESENFRIOL-ITO|          
|             JALISCO|               ARROZ|          
|              OAXACA|PEDIALYTE. ELECTR...|           
|            TLAXCALA|        AGUA SIN GAS|          
|VERACRUZ DE IGNAC...|              TOMATE|          
| MICHOACÁN DE OCAMPO|         PAN DE CAJA|         
|             YUCATÁN|       FLAGENASE 400|           
| MICHOACÁN DE OCAMPO|              ECTIVA|           
|             YUCATÁN|        SALSA CATSUP|           
|             YUCATÁN|            CLAVULIN|           
|             YUCATÁN|            CAPOTENA|           
|             JALISCO|       FLAGENASE 400|           
|             HIDALGO|              VERMOX|           
|              OAXACA|       MAIZ POZOLERO|           
|              OAXACA|                 AJO|            
+--------------------+--------------------+
only showing top 20 rows

和我的虚拟尝试:

df.groupBy('estado','producto').agg({'producto':'count'}).show()

+--------------------+--------------------+---------------+
|              estado|            producto|count(producto)|
+--------------------+--------------------+---------------+
|              MÉXICO|TINTE PARA EL CAB...|          44007|
|              MÉXICO|         TELEVISORES|          29702|
|              MÉXICO|              ACELGA|           7691|
|              MÉXICO|       QUESO. COTIJA|           4414|
|    DISTRITO FEDERAL|              AZUCAR|          18078|
|              MÉXICO|      DESENFRIOL-ITO|            642|
|             JALISCO|               ARROZ|          11735|
|              OAXACA|PEDIALYTE. ELECTR...|            302|
|            TLAXCALA|        AGUA SIN GAS|          14505|
|VERACRUZ DE IGNAC...|              TOMATE|            652|
| MICHOACÁN DE OCAMPO|         PAN DE CAJA|          13003|
|             YUCATÁN|       FLAGENASE 400|            313|
| MICHOACÁN DE OCAMPO|              ECTIVA|             39|
|             YUCATÁN|        SALSA CATSUP|           6549|
|             YUCATÁN|            CLAVULIN|            183|
|             YUCATÁN|            CAPOTENA|            271|
|             JALISCO|       FLAGENASE 400|            699|
|             HIDALGO|              VERMOX|            121|
|              OAXACA|       MAIZ POZOLERO|           1387|
|              OAXACA|                 AJO|            783|
+--------------------+--------------------+---------------+

但我需要与

类似的输出
+--------------------+--------------------+---------------+
|              estado|            producto|count(producto)|
+--------------------+--------------------+---------------+
|    DISTRITO FEDERAL|              AZUCAR|          18078|
|             HIDALGO|              VERMOX|            121|
|             JALISCO|               ARROZ|          11735|
|             JALISCO|       FLAGENASE 400|            699|
|              MÉXICO|TINTE PARA EL CAB...|          44007|
|              MÉXICO|         TELEVISORES|          29702|
|              MÉXICO|              ACELGA|           7691|
|              MÉXICO|       QUESO. COTIJA|           4414|
|              MÉXICO|      DESENFRIOL-ITO|            642|
| MICHOACÁN DE OCAMPO|         PAN DE CAJA|          13003|
| MICHOACÁN DE OCAMPO|              ECTIVA|             39|
|              OAXACA|       MAIZ POZOLERO|           1387|
|              OAXACA|                 AJO|            783|
|              OAXACA|PEDIALYTE. ELECTR...|            302|
|            TLAXCALA|        AGUA SIN GAS|          14505|
|VERACRUZ DE IGNAC...|              TOMATE|            652|
|             YUCATÁN|        SALSA CATSUP|           6549|
|             YUCATÁN|       FLAGENASE 400|            313|
|             YUCATÁN|            CLAVULIN|            183|
|             YUCATÁN|            CAPOTENA|            271|
+--------------------+--------------------+---------------+

甚至更好,为第一列的每个唯一变量显示第二列的唯一分类变量

+--------------------+--------------------+---------------+
|              estado|            producto|count(producto)|
+--------------------+--------------------+---------------+
|    DISTRITO FEDERAL|              AZUCAR|          18078|
|             HIDALGO|              VERMOX|            121|
|             JALISCO|               ARROZ|          11735|
|                    |       FLAGENASE 400|            699|
|              MÉXICO|TINTE PARA EL CAB...|          44007|
|                    |         TELEVISORES|          29702|
|                    |              ACELGA|           7691|
|                    |       QUESO. COTIJA|           4414|
|                    |      DESENFRIOL-ITO|            642|
| MICHOACÁN DE OCAMPO|         PAN DE CAJA|          13003|
|                    |              ECTIVA|             39|
|              OAXACA|       MAIZ POZOLERO|           1387|
|                    |                 AJO|            783|
|                    |PEDIALYTE. ELECTR...|            302|
|            TLAXCALA|        AGUA SIN GAS|          14505|
|VERACRUZ DE IGNAC...|              TOMATE|            652|
|             YUCATÁN|        SALSA CATSUP|           6549|
|                    |       FLAGENASE 400|            313|
|                    |            CLAVULIN|            183|
|                    |            CAPOTENA|            271|
+--------------------+--------------------+---------------+

我希望我的问题很清楚,我很抱歉我的英语不好。谢谢

更新:我忘了说在第三列 (count(producto)) 中只显示前 n 个最大的,比如说前三个最大的,类似于 Pandas 中的函数 nlargest()。

我想用这样的东西

df.groupBy('estado','producto').count().filter("'count'>=3").sort(asc("count"))

但我没试过。

更新 2

我已经用这个代码在 cmets 中尝试了一个建议

  df.groupBy("estado","producto").count()\
  .withColumn("row_num",F.row_number()\
  .over(Window.partitionBy("estado","producto")\
  .orderBy(F.col("count").desc())))\
  .filter(F.col("row_num") < 3)\
  .drop("row_num")\
  .orderBy(F.col("estado"), F.col("producto").desc(),F.col("count")\
  .desc()).show()

但输出不是我们想要的

+------+-------------+-----+
|estado|     producto|count|
+------+-------------+-----+
|  null|ZWAN. PREMIUM|   55|
|  null|         ZWAN|   55|
|  null|    ZUCARITAS|   20|
|  null|      ZOFILIP|    9|
|  null|    ZINTREPID|    9|
|  null|       ZINNAT|    9|
|  null|    ZANAHORIA|   14|
|  null|       ZACTOS|    9|
|  null|      YOGHURT|  203|
|  null|  YASMIN 24/4|    9|
|  null|       YASMIN|    9|
|  null|    XATRAL-OD|    8|
|  null|VYTORIN 10/20|    8|
|  null| VINO DE MESA|    7|
|  null|      VINAGRE|   66|
|  null|  VIDEOJUEGOS|    7|
|  null| VIDEOCAMARAS|    1|
|  null| VICK VAPORUB|   16|
|  null|       VIAGRA|   17|
|  null|  VERMOX PLUS|    9|
+------+-------------+-----+
only showing top 20 rows

我尝试稍微修改一下代码,但我明白了

+----------------+--------------------+------+
|          estado|            producto| count|
+----------------+--------------------+------+
|DISTRITO FEDERAL|            REFRESCO|287463|
|DISTRITO FEDERAL|                 FUD|207569|
|          MÉXICO|            REFRESCO|194939|
|DISTRITO FEDERAL|LECHE ULTRAPASTEU...|175640|
|DISTRITO FEDERAL|   DETERGENTE P/ROPA|173452|
|          MÉXICO|                 FUD|149141|
|DISTRITO FEDERAL|             YOGHURT|136720|
|DISTRITO FEDERAL|             CERVEZA|136686|
|          MÉXICO|   DETERGENTE P/ROPA|132862|
|DISTRITO FEDERAL|            MAYONESA|131103|
|DISTRITO FEDERAL|      CHILES EN LATA|130598|
|DISTRITO FEDERAL|    JABON DE TOCADOR|129889|
|DISTRITO FEDERAL|             SHAMPOO|125603|
|DISTRITO FEDERAL|      LECHE EN POLVO|116827|
|          MÉXICO|LECHE ULTRAPASTEU...|116522|
|DISTRITO FEDERAL|         DESODORANTE|113779|
|DISTRITO FEDERAL|               HUEVO|111412|
|DISTRITO FEDERAL|     TOALLA FEMENINA|102356|
|DISTRITO FEDERAL|           MARGARINA| 98235|
|          MÉXICO|    JABON DE TOCADOR| 97330|
+----------------+--------------------+------+
only showing top 20 rows

【问题讨论】:

    标签: group-by pyspark apache-spark-sql


    【解决方案1】:

    你的计数正确。您只需要使用 row_number 窗口选择前 3 个并正确排序结果。看看下面的代码。

    df.groupBy("estado","producto").count()
      .withColumn("row_num",row_number().over(Window.partitionBy("estado","producto").orderBy(col("count").desc)))
      .filter(col("row_num") <= 3)
      .drop("row_num")
      .orderBy(col("estado"), col("producto"), col("count").desc)
    

    检查此link 以在 Pyspark 中正确使用 row_number。 Spark SQL Row_number() PartitionBy Sort Desc

    【讨论】:

    • 感谢您的回答。我尝试了您建议的代码,但出现以下错误: Invalid argument, not a string or column: unary_op.. of Column> of type 。对于列字面量,使用“lit”、“array”、“struct”或“create_map”函数。
    • 它实际上在 scala 中。 Python api 应该有相同的方法。
    • 抱歉,我的答案编辑错误。错误消息是:。类型 的列>。对于列文字,使用 'lit'、'array'、'struct' 或 'create_map' 函数我的导入是: from pyspark.sql import SparkSession from pyspark import SparkContext from pyspark.sql.window import Window import pyspark.sql.functions as F from pyspark.sql.functions import desc
    • 窗口是 pyspark.sql.expressions.window 。
    • 如果运行 pyspark.sql.expressions.window 我得到:No module named 'pyspark.sql.expressions' but using pyspark.sql.window import Window 运行正常。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-10-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-04-11
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多