我花了相当多的时间阅读pyspark和spark-dataframe标签的一些问题,而且我经常发现海报没有提供足够的信息来真正理解他们的问题。我经常评论要求他们发布MCVE,但有时让他们显示一些样本输入/输出数据就像拔牙一样。例如:请参阅this question上的评论。
也许问题的一部分是人们根本不知道如何轻松地为火花数据帧创建MCVE。我认为将this pandas question的spark-dataframe版本作为可以链接的指南会很有用。
那么如何创建一个好的,可重复的例子?
答案 0 :(得分:48)
至少,海报应在其数据框和代码上提供几行和列,以便轻松创建它。简单来说,我的意思是剪切和粘贴。尽可能小,以证明您的问题。
我有以下数据框:
+-----+---+-----+----------+
|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'
em> 'X'
加上7天可以被列 '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|
+-----+---+-----+----------+------------+
中的值整除吗?
所需的输出:
date
详细解释如何获得所需的输出。它有助于显示示例计算。
例如,在第1行中,X = 1,日期= 2017-01-01。添加7天到目前为止2017-01-08。这个月的日期是8,因为8可以被1整除,答案是“是”&#39>。
同样,最后一行X = 7,日期= 2017-01-04。将7添加到日期会产生11作为该月的日期。由于11%7不是0,答案是“不”,
向我们展示您已完成或尝试过的内容,包括所有* 代码,即使它不起作用。告诉我们您遇到的问题,如果收到错误,请附上错误消息。
(*您可以省略代码以创建spark上下文,但您应该包括所有导入。)
我知道如何添加 from pyspark.sql import functions as f
df.withColumn("next_week", f.date_add("date", 7))
的新列加上7天,但我无法将该月的某一天作为整数。< / em>的
/* global globalValueHere */
答案 1 :(得分:21)
如果问题与性能调整有关,请包含以下信息。
最好包含扩展执行计划。在Python中:
df.explain(True)
在Scala中:
df.explain(true)
或包含统计信息的扩展执行计划。在Python中:
print(df._jdf.queryExecution().stringWithStats())
Scala中的:
df.queryExecution.stringWithStats
mode
- local
,client
,`cluster。 慢是相对的,特别是当您移植非分布式应用程序或预期低延迟时。可以从Spark UI(sc.uiWebUrl
)jobs
或Spark REST UI中检索不同任务和阶段的确切时间。
为每个上下文使用已建立的名称可以让我们快速重现问题。
sc
- 适用于SparkContext
。sqlContext
- 适用于SQLContext
。spark
- 适用于SparkSession
。强大的类型推断是Scala最有用的功能之一,但它很难分析脱离上下文的代码。即使从上下文中显而易见的类型,最好注释变量。喜欢
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 Idea
使用 Alt + =
答案 2 :(得分:14)
好问题&amp;回答;一些额外的建议:
Spark仍在不断发展,尽管没有1.x时那么快。它总是(但特别是如果你使用的是较旧的版本)一个好主意,包括你的工作版本。就个人而言,我总是以:
开始我的答案spark.version
# u'2.2.0'
或
sc.version
# u'2.2.0'
包括你的Python版本也不是一个坏主意。
如果你的问题不是严格关于Spark SQL&amp;数据帧,例如如果您打算在某些机器学习操作中使用您的数据框,请明确说明您的导入 - 请参阅this question,只有在(现已删除)评论中进行了大量交换后才在OP中添加导入(并且结果是这些错误的进口是问题的根本原因。)
为什么这有必要?因为,例如,这个LDA
from pyspark.mllib.clustering import LDA
与此LDA 不同:
from pyspark.ml.clustering import LDA
第一个来自旧的基于RDD的API(以前称为Spark MLlib),而第二个来自新的基于数据帧的API(Spark ML)。
好的,我承认这是主观的:我认为PySpark问题不应该默认标记为python
;问题是,python
标签自动代码突出显示(我相信这是使用PySpark问题的人的主要原因)。无论如何,如果您碰巧同意,并且您仍然想要一个很好的,突出显示的代码,只需包含相关的降价指令:
<!-- language-all: lang-python -->
在您的帖子中的某个位置,在您的第一个代码段之前。
[更新:I have requested自动语法突出显示pyspark
和sparkr
标签 - 最受欢迎的投票赞成]
答案 3 :(得分:12)
这个小帮助函数可能有助于将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])
<强> Scala的:强>
// 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 ,eqNullSafe
可以使用spark 2.3
。