注: 以下の翻訳の正確性は検証されていません。AIPを利用して英語版の原文から機械的に翻訳されたものです。
トランスフォームの入力と出力、軽量トランスフォームと PySpark トランスフォームの違いなど、基本的な概念については、トランスフォームを参照してください。
PySpark は、Apache Spark バックエンドと連携してデータを高速に処理できるラッパー言語です。Spark は、サーバーの分散ネットワーク全体で非常に大規模なデータセットを処理でき、正しく使用すれば、パフォーマンスと信頼性の面で大きなメリットがあります。ただし、特に SQL などのリレーショナルデータベースシステムに慣れている場合は、いくつかの制約もあります。たとえば、Spark は、ある行がどのサーバーのどの位置に存在するかを正確に把握できないため、特定の行を直接選択して更新または削除することはできません。このような方法でデータベースを扱うことに慣れている場合は、データセットを全体として捉え、行ではなく列に基づいてデータを処理するように、概念モデルを調整する必要があります。
ループ、リスト、変数など、手続き型の Python の構文に慣れている場合は、Python から移行するを参照して、PySpark の DataFrame オブジェクトの使い方を学んでください。
クエリの結果が「ビュー」(仮想テーブルの結果セット)になる SQL とは異なり、PySpark でデータセットを処理すると、まったく新しいデータセットが生成されます。これにより、派生データセットを基に新しいデータセットをビルドできるだけでなく、組織内のほかのメンバーも、中間データセットをご自身のデータ処理タスクに再利用できます。データオペレーティングシステムである Palantir Foundry では、データセットは親子(またはソースと結果)の有向ツリー関係によって自動的にリンクされます。これにより、誰でも Spark による変換のデータリネージを簡単にたどれます。つまり、データセットの依存関係がどのようにビルドされ、それらのデータセットがどこから来たのかを探索できます。また、組織内のほかのメンバーがデータセットをどのように使用しているかも見つけられるため、例から学んだり、重複する作業を効果的に減らしたりできます。
Code Workbook では、関数は次のようになります。
Copied!1 2 3 4def new_frame(old_frame): df = old_frame # df = transformations on df return df
old_frame:Foundry 内に保存されたデータセットを表す DataFrame を参照します。old_frame は不変であり、この new_frame 関数内では変更できません。ある意味では、変換の中間ステップはすべて、新しい不変のデータフレームを生成します。そのデータフレームをさらに加工したり、そのまま返したりできます。これは完全に正確な説明ではありませんが、考え方のモデルとして、コードをより整理しやすくなります。new_frame:この関数内で、old_frame に適用する一連の変換を定義できます。return 文では DataFrame(この例では df と呼んでいます)を返す必要があります。内部では、その DataFrame に適用したすべての変換がまとめられ、最適化されてから、入力データセットに適用されます。コードでビルドをトリガーすると、結果は Foundry 内の新しいデータセットファイルに保存され、ビルドの完了後に探索できます。DataFrame 内のデータは、Array でも Dictionary でもないため、直接参照できません。実際には、内部でパーティション分割やシャッフルが行われているため、どの時点でもデータの所在を特定することはできません。データセットの絞り込みや集計を行う場合を除き、コードはデータセットの内容にあまり依存しないものにする必要があります。並べ替えは一般にコストが高く、時間がかかるため、基本的には、行がランダムな順序で並んでいると想定し、列、フィルター、集計、そして創意工夫による問題解決に手段を絞ります。
PySpark は型安全ではなく、すべてのトランスフォーム操作の評価を試み、実行時にいずれかの操作が失敗すると処理を中断するため、入力される列のスキーマを把握しておくことが非常に重要です。
データ型が競合する場合の挙動は予測しにくいため、文字列や日付に数学関数を適用したり、数値に文字列操作を行ったり、整数に日付操作を行ったりしないでください。
値を操作する前に、必ず正しいデータ型にキャストしてください。
DataFrame の各列には名前が付いており、名前を変更できます。列名は一意で、大文字と小文字が区別されます。Foundry データセットでは、次のガイドラインに従ってください。
_(アンダースコア)で区切ります(スペースは使用できません)。camelCasedColumnNames は避けます。(、)、& などの特殊文字は使用しないでください。既存のコードを見ると、DataFrame を参照する変数の命名方法に厳密なルールがないことに気づくでしょう。このチートシートでは、DataFrame を df として参照しますが、ほかの例では raw、out、input、table、something_specific などが使われることもあります。目的を果たせるのであれば、どの名前でも構いません。
また、次のようなパターンも見られます。
Copied!1 2 3 4 5df = df.select("firstName", "age") df = df.withColumn("age", df.age.cast("integer")) df = df.filter(df.age > 21) df = df.withColumnRenamed("firstName", "first_name") return df
または、同じ処理を別の書き方で記述できます。
Copied!1 2 3 4return df.select("firstName", "age") \ .withColumn("age", df.age.cast("integer")) \ .filter(df.age > 21) \ .withColumnRenamed("firstName", "first_name")
コーディングに慣れていない方のために説明すると、= の左側にある df には、右側の df に適用された変換の結果が格納されてから、コードの次の行に進みます。この例では、結果を同じ名前の変数に格納しており、各ステップの後で df の内容を実質的に上書きしています。DataFrame の変換結果を別の名前の変数に格納することもできますが、ほとんどの場合は、同じ変数を上書きして次に進んでも問題ありません。各トランスフォーム関数の最後では、新しいデータフレームを、変数として(1つ目の例)、または最後の変換の結果として(2つ目の例)返す必要があります。
どちらの例も同じ処理を行います。
df の2列のみを選択します。age 列をキャストして、文字列ではなく Integer にします。age > 21 のエントリのみを含めます。firstName から first_name に変更します。結果のデータセットには first_name と age の2列のみが含まれ、21歳以下の人は除外されます。これが最終的な df の内容であり、return で返すことも、さらに変換を適用することもできます。以降のセクションでは、これらのトランスフォームを詳しく説明します。
ウィンドウ関数は、DataFrame オブジェクトの元の行や列を削除せずに、集計値やその他の計算値を追加します。累計、順位付け、移動平均に使用します。詳しくは、ウィンドウ関数を参照してください。
Foundry で PySpark を記述するためのツールには、Code Repositories と Code Workbook の2つがあります。
Code Repositories では、ほとんどの関数を使用するために、.py ドキュメントの先頭で次のインポート文を宣言する必要があります。
Copied!1from pyspark.sql import functions as F
Code Workbook では、これがグローバルインポートとしてすでに含まれているため、追加の設定なしでほとんどの関数を使用できます。
このリファレンスは網羅的なものではなく、一般的なパターンやベストプラクティスに関するガイダンスに重点を置いています。PySpark SQL 関数の完全な一覧については、公式の Apache Spark ドキュメント ↗を参照できます。
明快で読みやすく、保守しやすい PySpark コードを記述するためのガイダンスについては、PySpark スタイルガイドを参照してください。