web-dev-qa-db-ja.com

再現性の高いApacheを作成する方法Sparkの例

pyspark および spark-dataframe タグを使用していくつかの質問を読むのにかなりの時間を費やしてきましたが、非常に頻繁にポスターから十分な情報が得られないことがわかりました彼らの質問を本当に理解します。私は通常、彼らに [〜#〜] mcve [〜#〜] を投稿するようにコメントしますが、サンプルの入出力データを見せるようにすることは、歯を引っ張るようなものです。例: this question のコメントを参照してください。

おそらく問題の一部は、spark-dataframesのMCVEを簡単に作成する方法を知らないことです。リンクできるガイドとして、spark-dataframeバージョンの this pandas question があると便利だと思います。

それでは、どのようにして、良い、再現可能な例を作成するのでしょうか?

55
pault

簡単に再作成できる小さなサンプルデータを提供します。

少なくとも、ポスターは、データフレームとコードを簡単に作成するために使用できるコードの行と列を提供する必要があります。簡単に言うと、カットアンドペーストを意味します。問題を実証するために、できるだけ小さくしてください。


次のデータフレームがあります:

+-----+---+-----+----------+
|index|  X|label|      date|
+-----+---+-----+----------+
|    1|  1|    A|2017-01-01|
|    2|  3|    B|2017-01-02|
|    3|  5|    A|2017-01-03|
|    4|  7|    B|2017-01-04|
+-----+---+-----+----------+

このコードで作成できます:

df = sqlCtx.createDataFrame(
    [
        (1, 1, 'A', '2017-01-01'),
        (2, 3, 'B', '2017-01-02'),
        (3, 5, 'A', '2017-01-03'),
        (4, 7, 'B', '2017-01-04')
    ],
    ('index', 'X', 'label', 'date')
)

目的の出力を表示します。

特定の質問をして、希望する出力を表示してください。


新しい列を作成する方法'is_divisible'値を持つ'yes'月の日付の場合'date'プラス7日間は列の値で割り切れる'X'and'no'それ以外の場合?

望ましい出力:

+-----+---+-----+----------+------------+
|index|  X|label|      date|is_divisible|
+-----+---+-----+----------+------------+
|    1|  1|    A|2017-01-01|         yes|
|    2|  3|    B|2017-01-02|         yes|
|    3|  5|    A|2017-01-03|         yes|
|    4|  7|    B|2017-01-04|          no|
+-----+---+-----+----------+------------+

出力を取得する方法を説明します。

希望する出力を得る方法を詳細に説明してください。計算例を示すのに役立ちます。


たとえば、行1の場合、X = 1および日付= 2017-01-01。日付に7日を追加すると、2017-01-08になります。月の日は8です。8は1で割り切れるので、答えは「はい」です。

同様に、最後の行X = 7および日付= 2017-01-04。日付に7を追加すると、月の日として11が得られます。 11%7は0ではないため、答えは「いいえ」です。


既存のコードを共有します。

コードが機能しない場合でも、コードのall *を含めて、実行または試行した内容を表示します。行き詰まっている場所を教えてください。エラーが発生した場合は、エラーメッセージを含めてください。

(*コードを省略してsparkコンテキストを作成できますが、すべてのインポートを含める必要があります。)


新しい列を追加する方法は知っていますdateプラス7日間ですが、月の日を整数として取得するのに問題があります。

from pyspark.sql import functions as f
df.withColumn("next_week", f.date_add("date", 7))

バージョンを含め、インポートし、構文の強調表示を使用する


パフォーマンスチューニングの投稿の場合、実行計画を含める

  • 完全な詳細は この回答ser8371915 によって書かれました。
  • コンテキストに標準化された名前を使用すると役立ちます。

解析spark=出力ファイル

  • Max に役立つコードを提供しました この回答 解析に役立ちますSparkファイルをDataFrameに出力します。

その他の注意。

  • 最初に 質問方法最小、完全、検証可能な例を作成する方法 を必ず読んでください。
  • 上記のリンクにあるこの質問に対する他の回答を読んでください。
  • わかりやすいタイトルを付けてください。
  • 丁寧に。 SOの人はボランティアです。よろしくお願いします。
50
pault

性能調整

質問がパフォーマンスチューニングに関連している場合は、次の情報を含めてください。

実行計画

拡張実行計画を含めるのが最適です。 Pythonの場合:

df.explain(True) 

Scalaの場合:

df.explain(true)

または統計付きの拡張実行計画。 Pythonの場合:

print(df._jdf.queryExecution().stringWithStats())

scalaの場合:

df.queryExecution.stringWithStats

モードとクラスター情報

  • mode-localclient、 `cluster。
  • クラスターマネージャー(該当する場合)-なし(ローカルモード)、スタンドアロン、YARN、Mesos、Kubernetes。
  • 基本的な構成情報(コアの数、エグゼキューターのメモリ)。

タイミング情報

slowは相対的です。特に、非分散アプリケーションを移植する場合、または低遅延が予想される場合は重要です。さまざまなタスクとステージの正確なタイミングは、Spark UI(sc.uiWebUrljobsまたはSpark=REST UI。

コンテキストに標準化された名前を使用する

各コンテキストに確立された名前を使用すると、問題をすばやく再現できます。

  • sc-SparkContextの場合。
  • sqlContext-SQLContextの場合。
  • spark-SparkSessionの場合。

型情報を提供する(Scala

強力な型推論はScalaの最も便利な機能の1つですが、コンテキストから取り出されたコードを分析するのが難しくなります。型がコンテキストから明らかな場合でも、変数に注釈を付ける方が適切です。好む

val lines: RDD[String] = sc.textFile("path")
val words: RDD[String] = lines.flatMap(_.split(" "))

以上

val lines = sc.textFile("path")
val words = lines.flatMap(_.split(" "))

一般的に使用されるツールはあなたを助けることができます:

  • spark-Shell/Scala Shell

    つかいます :t

    scala> val rdd = sc.textFile("README.md")
    rdd: org.Apache.spark.rdd.RDD[String] = README.md MapPartitionsRDD[1] at textFile at <console>:24
    
    scala> :t rdd
    org.Apache.spark.rdd.RDD[String]
    
  • InteliJのアイデア

    つかいます Alt + =

21
hi-zir

質疑応答;追加の提案:

Sparkバージョン

Sparkはまだ進化していますが、1.xの頃ほど急速ではありません。作業中のバージョンを含めることは常に(ただし、多少古いバージョンを使用している場合は特に)良いアイデアです。個人的に、私はいつもanswersを次のように開始します:

spark.version
# u'2.2.0'

または

sc.version
# u'2.2.0'

Pythonバージョンも含めることは、決して悪い考えではありません。


すべてのインポートを含める

質問が厳密にSpark= SQLおよびデータフレームに関するものではない場合、たとえば、何らかの機械学習操作でデータフレームを使用する場合は、インポートについて明示してください- この質問 を参照してください=、ここで(現在削除された)コメントの広範な交換の後にのみインポートがOPに追加されました(これらの誤ったインポートが問題の根本原因であることが判明しました)。

なぜこれが必要なのですか?たとえば、このLDA

from pyspark.mllib.clustering import LDA

このLDAとはdifferent

from pyspark.ml.clustering import LDA

最初は古いRDDベースのAPI(以前のSpark MLlib)からのもので、2番目は新しいデータフレームベースのAPI(Spark ML)からのものです。


コードの強調表示を含める

OK、これは主観的であると告白します。PySparkの質問には、デフォルトでpythonのタグを付けるべきではないと思います;問題は、pythonタグが自動的にコードの強調表示を行うことです(そして、これがPySparkの質問に使用する主な理由だと思います)。とにかく、あなたがたまたま同意して、それでもニースの強調表示されたコードが欲しいなら、単に関連するマークダウンディレクティブを含めてください:

<!-- language-all: lang-python -->

投稿のどこか、最初のコードスニペットの前。

[更新: 要求しましたpysparkおよびsparkrタグの自動構文強調表示-歓迎します]

15
desertnaut

この小さなヘルパー関数は、Spark DataFrameへの出力ファイルの解析に役立ちます。

PySpark:

from pyspark.sql.functions import *

def read_spark_output(file_path):
    step1 = spark.read \
             .option("header","true") \
             .option("inferSchema","true") \
             .option("delimiter","|") \
             .option("parserLib","UNIVOCITY") \
             .option("ignoreLeadingWhiteSpace","true") \
             .option("ignoreTrailingWhiteSpace","true") \
             .option("comment","+") \
             .csv("file://{}".format(file_path))
    # select not-null columns
    step2 = t.select([c for c in t.columns if not c.startswith("_")])
    # deal with 'null' string in column
    return step2.select(*[when(~col(col_name).eqNullSafe("null"), col(col_name)).alias(col_name) for col_name in step2.columns])

スカラ:

// read Spark Output Fixed width table:
def readSparkOutput(filePath: String): org.Apache.spark.sql.DataFrame = {
  val step1 = spark.read
    .option("header", "true")
    .option("inferSchema", "true")
    .option("delimiter", "|")
    .option("parserLib", "UNIVOCITY")
    .option("ignoreLeadingWhiteSpace", "true")
    .option("ignoreTrailingWhiteSpace", "true")
    .option("comment", "+")
    .csv(filePath)

  val step2 = step1.select(step1.columns.filterNot(_.startsWith("_c")).map(step1(_)): _*)

  val columns = step2.columns
  columns.foldLeft(step2)((acc, c) => acc.withColumn(c, when(col(c) =!= "null", col(c))))
}

使用法:

df = read_spark_output("file:///tmp/spark.out")

PS:pysparkの場合、eqNullSafespark 2.3

12
MaxU