PySpark:用两列变量进行分类并按升序排列

时间:2019-03-17 21:11:56

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

我在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

我已尝试使用此代码在注释中提出建议

  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

1 个答案:

答案 0 :(得分:0)

You are counting properly. You just need to use row_number window to select the top 3 and order the results properly. Have look at the code below.

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)

Check this link中已保存的.html文件中的所有链接,以正确使用Pyspark中的row_number。 Spark SQL Row_number() PartitionBy Sort Desc