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)比在单独的数据上洗牌更有意义。

您应该提供一些易于复制/粘贴的数据,以便我们可以根据您的确切使用情况尝试修复您的问题。完成。希望现在更容易理解。您应该提供一些易于复制/粘贴的数据,以便我们可以根据您的确切用例尝试修复您的问题。完成。希望现在能更容易理解。