ApacheSparkのリストとしてデータフレームの列値を抽出します


87

データフレームの文字列列をリストに変換したい。DataframeAPIからわかるのはRDDなので、まずRDDに変換してtoArrayから、RDDに関数を適用してみました。この場合、長さとSQLは問題なく機能します。ただし、RDDから取得した結果には、このようなすべての要素を角かっこで囲んでいます[A00001]。列をリストに変換する適切な方法や、角かっこを削除する方法があるかどうか疑問に思いました。

任意の提案をいただければ幸いです。ありがとうございました!


回答:


117

これにより、単一のリストを含むコレクションが返されます。

dataFrame.select("YOUR_COLUMN_NAME").rdd.map(r => r(0)).collect()

マッピングがないと、データベースのすべての列を含むRowオブジェクトを取得するだけです。

これにより、おそらく任意のタイプのリストが表示されることに注意してください。結果タイプを指定する場合は、r => r(0).asInstanceOf[YOUR_TYPE]マッピングで.asInstanceOf [YOUR_TYPE]を使用できます。

PS自動変換のため、.rddパーツをスキップできます。


3
いくつかの奇妙な理由で、それは逆に機能します(Spark 2.1.0)collect().map(r => r(0))-この順序には不利な点がありますか?
Boern 2017年

1
遅くなる可能性があります-ソリューションは最初にドライバーのすべてのデータを収集し、その後、単一のドライバーの処理能力のみを使用して、ドライバーのマッピングを実行します(エグゼキューターの支援なし)。
TheMP 2017年

73

Spark2.xおよびScala2.11を使用

特定の列の値をリストに変換する3つの可能な方法を考えます。

すべてのアプローチに共通のコードスニペット

import org.apache.spark.sql.SparkSession

val spark = SparkSession.builder.getOrCreate    
import spark.implicits._ // for .toDF() method

val df = Seq(
    ("first", 2.0),
    ("test", 1.5), 
    ("choose", 8.0)
  ).toDF("id", "val")

アプローチ1

df.select("id").collect().map(_(0)).toList
// res9: List[Any] = List(one, two, three)

今、何が起きた?collect()各レコードから要素ゼロを使用してドライバーにデータを収集しています。

これはそれを行うための優れた方法ではありませんでした。次のアプローチで改善しましょう。


アプローチ2

df.select("id").rdd.map(r => r(0)).collect.toList 
//res10: List[Any] = List(one, two, three)

どうですか?単一のドライバーではなく、ワーカー間でマップ変換の負荷を分散しました。

rdd.map(r => r(0))はあなたがエレガントに見えないことを知っています。それでは、次のアプローチで対処しましょう。


アプローチ3

df.select("id").map(r => r.getString(0)).collect.toList 
//res11: List[String] = List(one, two, three)

ここでは、DataFrameをRDDに変換していません。見てmap、それは受け付けませんr => r(0)(または_(0)起因するデータフレーム内エンコーダの問題に以前のアプローチとして)。したがって、使用r => r.getString(0)することになり、Sparkの次のバージョンで対処されることになります。

結論

すべてのオプションで同じ出力が得られますが、2と3が効果的で、最後に3番目のオプションが効果的でエレガントです(私は思います)。

Databricksノートブック


24

私は与えられて求められた答えがScalaに想定されていることを知っているので、PySparkユーザーが興味を持っている場合に備えてPythonコードの小さなスニペットを提供しています。構文は与えられた答えに似ていますが、リストを適切にポップアウトするには、実際にはマッピング関数で列名をもう一度参照する必要があり、selectステートメントは必要ありません。

つまり、「Raw」という名前の列を含むDataFrame

「Raw」の各行の値をリストとして結合し、各エントリが「Raw」の行の値であるようにするには、次のようにします。

MyDataFrame.rdd.map(lambda x: x.Raw).collect()

4
これにより、Rowオブジェクトのリストが表示されます。値のリストが必要な場合はどうなりますか?
thatDataGuy 2016年

これにより、値のリストが表示されます。
abby sobh 2016

これを共有してくれてありがとう!これは、これを高速化する方法があるかどうか疑問に思っているだけで、非常にうまく機能します。実行速度はかなり遅くなります
MojganMazouchi20年

5

ScalaとSpark2 +で、これを試してください(列名が「s」であると仮定します)。 df.select('s).as[String].collect


3
sqlContext.sql(" select filename from tempTable").rdd.map(r => r(0)).collect.toList.foreach(out_streamfn.println) //remove brackets

それは完璧に動作します


2
from pyspark.sql.functions import col

df.select(col("column_name")).collect()

ここで収集するのは、それをリストに変換する関数です。巨大なデータセットのリストを使用することに注意してください。パフォーマンスが低下します。データを確認することをお勧めします。


1
List<String> whatever_list = df.toJavaRDD().map(new Function<Row, String>() {
    public String call(Row row) {
        return row.getAs("column_name").toString();
    }
}).collect();

logger.info(String.format("list is %s",whatever_list)); //verification

java(Real Programming Language)で誰も解決策を与えていないので、後で私に感謝することができます


0

リストを取得する更新されたソリューション:

dataFrame.select("YOUR_COLUMN_NAME").map(r => r.getString(0)).collect.toList


弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.