val rdd = sc.parallelize(Seq(("vskp", Array(2.0, 1.0, 2.1, 5.4)),("hyd",Array(1.5, 0.5, 0.9, 3.7)),("hyd", Array(1.5, 0.5, 0.9, 3.2)),("tvm", Array(8.0, 2.9, 9.1, 2.5))))
val df1= rdd.toDF("id", "vals")
val rdd1 = sc.parallelize(Seq(("vskp","ap"),("hyd","tel"),("bglr","kkt")))
val df2 = rdd1.toDF("id", "state")
val df3 = df1.join(df2,df1("id")===df2("id"),"left")
結合操作は正常に機能しますが、df2を再利用すると、未解決の属性エラーが発生します
val rdd2 = sc.parallelize(Seq(("vskp", "Y"),("hyd", "N"),("hyd", "N"),("tvm", "Y")))
val df4 = rdd2.toDF("id","existance")
val df5 = df4.join(df2,df4("id")===df2("id"),"left")
エラー:org.Apache.spark.sql.AnalysisException:解決された属性ID#426
私のコメントで述べたように、それは https://issues.Apache.org/jira/browse/SPARK-10925 に関連しており、より具体的には https://issues.Apache。 org/jira/browse/SPARK-14948 。参照を再利用すると命名にあいまいさが生じるため、dfのクローンを作成する必要があります。 https://issues.Apache.org/jira/browse/SPARK-14948 の最後のコメントを参照してください。例。
Df1とdf1から派生したdf2がある場合、結合後に2つの列が同じ名前を持たないようにdf2のすべての列の名前を変更してみてください。参加する前に:
df1.join(df2...
の代わりに
行う
# Step 1 rename shared column names in df2.
df2_renamed = df2.withColumnRenamed('columna', 'column_a_renamed').withColumnRenamed('columnb', 'column_b_renamed')
# Step 2 do the join on the renamed df2 such that no two columns have same name.
df1.join(df2_renamed)
2つの連続した結合で1つのDataFrameを使用しようとすると、同じ問題が発生しました。
問題は次のとおりです。DataFrameAには2つの列があり(xおよびyと呼びましょう)、DataFrame Bにも2つの列があります(wおよびzと呼びましょう)。 x = zでAとBを結合してから、y = zでそれらを結合する必要があります。
(A join B on A.x=B.z) as C join B on C.y=B.z
2回目の結合で「解決された属性B.z#1234 ...」という文句を言っているという正確なエラーが表示されていました。
@Erikが提供したリンク、および他のいくつかのブログと質問に従って、私はBのクローンが必要だと思いました。
ここに私がやったことがあります:
val aDF = ...
val bDF = ...
val bCloned = spark.createDataFrame(bDF.rdd, bDF.schema)
aDF.join(bDF, aDF("x") === bDF("z")).join(bCloned, aDF("y") === bCloned("z"))
私の経験から、2つの解決策があります。1)clone DF 2)テーブルを結合する前にあいまいな列の名前を変更します。 (重複した結合キーを削除することを忘れないでください)
個人的には、最初の方法でDFのクローンを作成するのに時間がかかるため、特にデータサイズが大きい場合は、2番目の方法を好みます。
以下を行うと動作します。
データフレームがあるとします。 df1と同じデータフレームをクロス結合する場合は、以下を使用できます
df1.toDF("ColA","ColB").as("f_df").join(df1.toDF("ColA","ColB").as("t_df"),
$"f_df.pcmdty_id" ===
$"t_df.assctd_pcmdty_id").select($"f_df.pcmdty_id",$"f_df.assctd_pcmdty_id")
Java開発者の場合、このメソッドを呼び出してみてください。
private static Dataset<Row> cloneDataset(Dataset<Row> ds) {
List<Column> filterColumns = new ArrayList<>();
List<String> filterColumnsNames = new ArrayList<>();
scala.collection.Iterator<StructField> it = ds.exprEnc().schema().toIterator();
while (it.hasNext()) {
String columnName = it.next().name();
filterColumns.add(ds.col(columnName));
filterColumnsNames.add(columnName);
}
ds = ds.select(JavaConversions.asScalaBuffer(filterColumns).seq()).toDF(scala.collection.JavaConverters.asScalaIteratorConverter(filterColumnsNames.iterator()).asScala().toSeq());
return ds;
}
結合する直前の両方のデータセットで、データセットを新しいものに複製します。
df1 = cloneDataset(df1);
df2 = cloneDataset(df2);
Dataset<Row> join = df1.join(df2, col("column_name"));
// if it didn't work try this
final Dataset<Row> join = cloneDataset(df1.join(df2, columns_seq));