Python 使用自身的筛选器和同名列连接PySpark dataframe
我有一个Python 使用自身的筛选器和同名列连接PySpark dataframe,python,apache-spark,pyspark,Python,Apache Spark,Pyspark,我有一个目标数据帧,如下所示: rdd_1 = sc.parallelize([(0,"A",2), (1,"B",1), (2,"A",2)]) rdd_2 = sc.parallelize([(0,223,"201603"), (1,3213,"201602"), (2,2321,"201601")]) df_tg = sqlContext.createDataFrame(rdd_1, ["id", "route_a", "route_b"]) df_data = sqlContext.cr
目标
数据帧,如下所示:
rdd_1 = sc.parallelize([(0,"A",2), (1,"B",1), (2,"A",2)])
rdd_2 = sc.parallelize([(0,223,"201603"), (1,3213,"201602"), (2,2321,"201601")])
df_tg = sqlContext.createDataFrame(rdd_1, ["id", "route_a", "route_b"])
df_data = sqlContext.createDataFrame(rdd_2, ["id", "cost", "date"])
df_tg.show()
+---+-------+-------+
| id|route_a|route_b|
+---+-------+-------+
| 0| A| 2|
| 1| B| 1|
| 2| A| 2|
+---+-------+-------+
df_data[df_data.date == "201603"]
以及关于另一个带有时间戳的数据帧的更多信息:
df_data.show()
+---+----+------+
| id|cost| date|
+---+----+------+
| 0| 223|201603|
| 1|3213|201602|
| 2|2321|201601|
+---+----+------+
我需要创建新列连接数据帧,但按日期:
df_data_m1 = df_data[df_data.date == "201603"]
df_data_m2 = df_data[df_data.date == "201602"]
df_data_m3 = df_data[df_data.date == "201601"]
现在我需要创建新的列:
df = df_tg.join(df_data_m1, df_data_m1.id == df_tg.id)
但这会产生一个问题,即我们必须删除并重命名该列,以便我们不会覆盖以前的日期:
df = df_tg.join(df_data_m1, df_data_m1.id == df_tg.id).drop(df_data_m1.id).withColumnRenamed("cost", "cost_201603")
df = df.join(df_data_m2, df_data_m2.id == df_tg.id).drop(df_data_m2.id).withColumnRenamed("cost", "cost_201602")
我们必须为每个专栏,每个月都这样做,所以这是很多代码,即使我们编写了一个UDF来处理这个问题。有没有直接执行的方法?处理重复列的最简单方法是根本不生成这些列。如果您所拥有的只是等联接,那么您所需要的就是正确的
join
。Spark为以下情况提供了特殊语法:您只需枚举联接列:
tmp = df_tg.join(df_data, ["id"])
tmp.printSchema()
## root
## |-- id: long (nullable = true)
## |-- route_a: string (nullable = true)
## |-- route_b: long (nullable = true)
## |-- cost: long (nullable = true)
## |-- date: string (nullable = true)
在旁注上,代码的剩余部分有点可疑。如果未按如下方式对每个筛选器进行分区DataFrame
:
rdd_1 = sc.parallelize([(0,"A",2), (1,"B",1), (2,"A",2)])
rdd_2 = sc.parallelize([(0,223,"201603"), (1,3213,"201602"), (2,2321,"201601")])
df_tg = sqlContext.createDataFrame(rdd_1, ["id", "route_a", "route_b"])
df_data = sqlContext.createDataFrame(rdd_2, ["id", "cost", "date"])
df_tg.show()
+---+-------+-------+
| id|route_a|route_b|
+---+-------+-------+
| 0| A| 2|
| 1| B| 1|
| 2| A| 2|
+---+-------+-------+
df_data[df_data.date == "201603"]
需要对所有记录进行线性扫描
我不太清楚您的目标是什么,但如果您想为写入操作分离数据,可以在受支持的写入程序中使用partitionBy
方法:
tmp.write.partitionBy("date")
在其他情况下,可能是更好的选择
最后,如果您计划应用某些聚合,则与对分离的数据执行此操作相比,洗牌一次(
groupBy
or)更有意义。处理重复列的最简单方法是根本不生成这些列。如果您所拥有的只是等联接,那么您所需要的就是正确的join
。Spark为以下情况提供了特殊语法:您只需枚举联接列:
tmp = df_tg.join(df_data, ["id"])
tmp.printSchema()
## root
## |-- id: long (nullable = true)
## |-- route_a: string (nullable = true)
## |-- route_b: long (nullable = true)
## |-- cost: long (nullable = true)
## |-- date: string (nullable = true)
在旁注上,代码的剩余部分有点可疑。如果未按如下方式对每个筛选器进行分区DataFrame
:
rdd_1 = sc.parallelize([(0,"A",2), (1,"B",1), (2,"A",2)])
rdd_2 = sc.parallelize([(0,223,"201603"), (1,3213,"201602"), (2,2321,"201601")])
df_tg = sqlContext.createDataFrame(rdd_1, ["id", "route_a", "route_b"])
df_data = sqlContext.createDataFrame(rdd_2, ["id", "cost", "date"])
df_tg.show()
+---+-------+-------+
| id|route_a|route_b|
+---+-------+-------+
| 0| A| 2|
| 1| B| 1|
| 2| A| 2|
+---+-------+-------+
df_data[df_data.date == "201603"]
需要对所有记录进行线性扫描
我不太清楚您的目标是什么,但如果您想为写入操作分离数据,可以在受支持的写入程序中使用partitionBy
方法:
tmp.write.partitionBy("date")
在其他情况下,可能是更好的选择
最后,如果您计划应用一些聚合,则一次洗牌(
groupBy
or)比在单独的数据上洗牌更有意义。您应该提供一些易于复制/粘贴的数据,以便我们可以根据您的确切使用情况尝试修复您的问题。完成。希望现在更容易理解。您应该提供一些易于复制/粘贴的数据,以便我们可以根据您的确切用例尝试修复您的问题。完成。希望现在能更容易理解。