web-dev-qa-db-ja.com

AnalysisExceptionを解決する方法:Sparkで解決された属性

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

21
Rajita

私のコメントで述べたように、それは 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 の最後のコメントを参照してください。例。

21

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)
4
Tomer Ben David

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"))
1
Iraj Hedayati

私の経験から、2つの解決策があります。1)clone DF 2)テーブルを結合する前にあいまいな列の名前を変更します。 (重複した結合キーを削除することを忘れないでください)

個人的には、最初の方法でDFのクローンを作成するのに時間がかかるため、特にデータサイズが大きい場合は、2番目の方法を好みます。

0
Zhenyi Lin

以下を行うと動作します。

データフレームがあるとします。 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")
0
dharani sugumar

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)); 
0