Pyspark基于条件的数据框架

时间:2018-05-10 00:06:45

标签: apache-spark pyspark

我在pyspark中有一个数据框,如下所示。

df.show()

+---+-------+----+
| id|   type|s_id|
+---+-------+----+
|  1|    ios|  11|
|  1|    ios|  12|
|  1|    ios|  13|
|  1|    ios|  14|
|  1|android|  15|
|  1|android|  16|
|  1|android|  17|
|  2|    ios|  21|
|  2|android|  18|
+---+-------+----+

现在从这个数据框中我想通过旋转来创建另一个数据框。

df1.show()
+---+-----+-----+-----+---------+---------+---------+
| id| ios1| ios2| ios3| android1| android2| android3|
+---+-----+-----+-----+---------+---------+---------+
|  1|   11|   12|   13|       15|       16|       17|
|  2|   21| Null| Null|       18|     Null|     Null|
+---+-----+-----+-----+---------+---------+---------+

在这里,我需要考虑每个Id的条件,即使3 types超过3 or less than 3 new_df.show() +---+-------+----+ | id| type|s_id| +---+-------+----+ | 1| ios| 11| | 1| ios| 12| | 1| | 13| | 1| | 14| | 1|andriod| 15| | 1| | 16| | 1| | 17| | 2|andriod| 18| | 2| ios| 21| +---+-------+----+ ,我也只想考虑+---+----+----+----+--------+----+----+ | id| 1| 2| 3|andriod1|ios1|ios2| +---+----+----+----+--------+----+----+ | 1| 13| 14| 16| 15| 11| 12| | 2|null|null|null| 18| 21|null| +---+----+----+----+--------+----+----+

我该怎么做?

  

修改

+---+--------+--------+--------+----+----+----+
|id |android1|android2|android3|ios1|ios2|ios3|
+---+--------+--------+--------+----+----+----+
|1  |15      |    null|    null|  11|  12|null|
|2  |18      |    null|    null|  21|null|null|
+---+--------+--------+--------+----+----+----+

我得到的结果是

pcl::PointCloud<pcl::PointXYZ>::Ptr cloud(new pcl::PointCloud<pcl::PointXYZ>);
pcl::io::loadPCDFile<pcl::PointXYZ>("points.pcd",  *cloud );

我想要的是

boost::shared_ptr

1 个答案:

答案 0 :(得分:1)

使用以下逻辑可以获得所需的结果。

Window函数用于为id订购的每个types_id组生成行号。生成的行号用于filterconcat type。然后最后分组和旋转应该为您提供所需的输出

from pyspark.sql import Window 
windowSpec = Window.partitionBy("id", "type").orderBy("s_id")

from pyspark.sql import functions as f

df.withColumn("ranks", f.row_number().over(windowSpec))\
    .filter(f.col("ranks") < 4)\
    .withColumn("type", f.concat(f.col("type"), f.col("ranks")))\
    .drop("ranks")\
    .groupBy("id")\
    .pivot("type")\
    .agg(f.first("s_id"))\
    .show(truncate=False)

应该给你

+---+--------+--------+--------+----+----+----+
|id |android1|android2|android3|ios1|ios2|ios3|
+---+--------+--------+--------+----+----+----+
|1  |15      |16      |17      |11  |12  |13  |
|2  |18      |null    |null    |21  |null|null|
+---+--------+--------+--------+----+----+----+

回答已编辑的部分

需要一个额外的过滤器作为

df.withColumn("ranks", f.row_number().over(windowSpec)) \
    .filter(f.col("ranks") < 4) \
    .filter(f.col("type") != "") \
    .withColumn("type", f.concat(f.col("type"), f.col("ranks"))) \
    .drop("ranks") \
    .groupBy("id") \
    .pivot("type") \
    .agg(f.first("s_id")) \
    .show(truncate=False)

会给你

+---+--------+----+----+
|id |andriod1|ios1|ios2|
+---+--------+----+----+
|1  |15      |11  |12  |
|2  |18      |21  |null|
+---+--------+----+----+

现在这个数据框缺少android2, android3 and ios3列。因为它们不存在于更新的输入数据中。您可以使用withColumn api添加它们并填充空值