dplyr 0.7的发布包括对dplyr 进行编程的重大改进.我仔细阅读了本文档,并试图了解它对我使用dplyr的影响.
这是我在使用dplyr构建报告和聚合函数时使用的常用习惯用法:
my_report <- function(data, grouping_vars) {
data %>%
group_by_(.dots=grouping_vars) %>%
summarize(x_mean=mean(x), x_median=median(x), ...)
}
Run Code Online (Sandbox Code Playgroud)
这grouping_vars是一个字符串向量.
我喜欢这个成语,因为我可以从其他地方传递字符串向量,例如文件或Shiny应用程序的反应性UI,但它对于交互式工作也不是太糟糕.
但是,在使用dplyr vignette的新编程中,我没有看到使用新的dplyr可以完成这样的事情的示例.我只看到传递字符串不再是正确方法的示例,我必须使用quosures.
我很高兴采用quosures,但是我如何从字符串到dplyr预期的这些情况呢?期望整个R生态系统向dplyr提供数据似乎是不可行的 - 很多时候我们将获得字符串并且它们必须被转换.
这是一个示例,显示您现在应该做什么,以及我的旧习语如何不起作用:
library(dplyr)
grouping_vars <- quo(am)
mtcars %>%
group_by(!!grouping_vars) %>%
summarise(mean_cyl=mean(cyl))
#> # A tibble: 2 × 2
#> am mean_cyl
#> <dbl> <dbl>
#> 1 0 6.947368
#> 2 1 5.076923
grouping_vars <- "am"
mtcars %>%
group_by(!!grouping_vars) %>%
summarise(mean_cyl=mean(cyl))
#> # A tibble: 1 × 2
#> …Run Code Online (Sandbox Code Playgroud) 我正在修补PySpark文档中的一些交叉验证代码,并尝试让PySpark告诉我选择了哪个模型:
from pyspark.ml.classification import LogisticRegression
from pyspark.ml.evaluation import BinaryClassificationEvaluator
from pyspark.mllib.linalg import Vectors
from pyspark.ml.tuning import ParamGridBuilder, CrossValidator
dataset = sqlContext.createDataFrame(
[(Vectors.dense([0.0]), 0.0),
(Vectors.dense([0.4]), 1.0),
(Vectors.dense([0.5]), 0.0),
(Vectors.dense([0.6]), 1.0),
(Vectors.dense([1.0]), 1.0)] * 10,
["features", "label"])
lr = LogisticRegression()
grid = ParamGridBuilder().addGrid(lr.regParam, [0.1, 0.01, 0.001, 0.0001]).build()
evaluator = BinaryClassificationEvaluator()
cv = CrossValidator(estimator=lr, estimatorParamMaps=grid, evaluator=evaluator)
cvModel = cv.fit(dataset)
Run Code Online (Sandbox Code Playgroud)
在PySpark shell中运行它,我可以得到线性回归模型的系数,但我似乎无法找到lr.regParam交叉验证程序选择的值.有任何想法吗?
In [3]: cvModel.bestModel.coefficients
Out[3]: DenseVector([3.1573])
In [4]: cvModel.bestModel.explainParams()
Out[4]: ''
In [5]: cvModel.bestModel.extractParamMap()
Out[5]: {}
In [15]: cvModel.params
Out[15]: [] …Run Code Online (Sandbox Code Playgroud) modeling cross-validation pyspark apache-spark-ml apache-spark-mllib
偶尔人们会在Python中引用"类X"对象.例:
data_iter_maker - 一个零参数可调用,它返回一个类似于dict的数据对象的迭代器.
"dict-like"是否有一个精确的定义,如果有,它是什么?它是一个x可以像字典一样被索引的对象:x[a],哪里a是可以清洗的?在这种情况下,一个namedtuple可能不会被视为类似dict,因为你不能使用像x['a'](我最后检查你必须写x.a)的表达式索引.但另一方面,namedtuples在功能上与dicts相似,我不知道该怎么想.
讽刺的是,我很想猜测"dict-like"的意思是"一个类似的对象,足以说明我的代码会产生相同的答案,就像你提交了一个语义上相同的dict对象一样".换句话说,"运行函数并自己找出你的论点是否像dict一样!"
更一般地说,是一个类似X的对象,它实现与X相同的接口?
我试图通过将它映射到RDD然后返回到DataFrame来清理Spark DataFrame.这是一个玩具示例:
def replace_values(row,sub_rules):
d = row.asDict()
for col,old_val,new_val in sub_rules:
if d[col] == old_val:
d[col] = new_val
return Row(**d)
ex = sc.parallelize([{'name': 'Alice', 'age': 1},{'name': 'Bob', 'age': 2}])
ex = sqlContext.createDataFrame(ex)
(ex.map(lambda row: replace_values(row,[(col,1,3) for col in ex.columns]))
.toDF(schema=ex.schema))
Run Code Online (Sandbox Code Playgroud)
运行上面的代码会产生Py4JError一个非常长的堆栈跟踪,结尾如下:
Py4JError: An error occurred while calling o801.__getnewargs__. Trace:
py4j.Py4JException: Method __getnewargs__([]) does not exist
at py4j.reflection.ReflectionEngine.getMethod(ReflectionEngine.java:333)
at py4j.reflection.ReflectionEngine.getMethod(ReflectionEngine.java:342)
at py4j.Gateway.invoke(Gateway.java:252)
at py4j.commands.AbstractCommand.invokeMethod(AbstractCommand.java:133)
at py4j.commands.CallCommand.execute(CallCommand.java:79)
at py4j.GatewayConnection.run(GatewayConnection.java:207)
at java.lang.Thread.run(Thread.java:745)
Run Code Online (Sandbox Code Playgroud)
这里发生了什么?我如何解决它?我正在使用PySpark 1.5.2.
在Python中,当子类化元组时,__new__使用self作为参数调用该函数.例如,这是PySpark Row类的一个释义版本:
class Row(tuple):
def __new__(self, args):
return tuple.__new__(self, args)
Run Code Online (Sandbox Code Playgroud)
但help(tuple)没有显示出self参数__new__:
__new__(*args, **kwargs) from builtins.type
Create and return a new object. See help(type) for accurate signature.
Run Code Online (Sandbox Code Playgroud)
并help(type)说了同样的话:
__new__(*args, **kwargs)
Create and return a new object. See help(type) for accurate signature.
Run Code Online (Sandbox Code Playgroud)
那么如何在类定义中self传递?__new__Row
*args吗?__new__有一些细微之处,其中它的签名可以与情境改变?是否有可能查看源代码,tuple.__new__以便我可以自己查看答案?
我的问题不是这个问题的重复,因为在那个问题中,所有的讨论都是指__new__明确拥有self或cls作为第一个参数的方法.我想了解一下
tuple.__new__方法没有self或 …我对使用Spark SQL(1.6)执行以下形式的“过滤的等联接”感兴趣
A inner join B where A.group_id = B.group_id and pair_filter_udf(A[cols], B[cols])
Run Code Online (Sandbox Code Playgroud)
这里的group_id是粗略的:单个值group_id可以与A和B中的10,000条记录相关联。
如果等值联接是由自身执行的,如果没有pair_filter_udf,则的粗略性group_id会产生计算问题。例如,对于group_id在A和B中都有10,000条记录的a,联接中将有1亿个条目。如果我们有成千上万个如此大的组,我们将生成一个巨大的表,并且很容易耗尽内存。
因此,至关重要的是我们向下推pair_filter_udf入连接并在生成对时对其进行过滤,而不是等到所有对都生成后再进行过滤。我的问题是Spark SQL是否这样做。
我建立了一个简单的过滤式等联接,并询问Spark的查询计划是什么:
# run in PySpark Shell
import pyspark.sql.functions as F
sq = sqlContext
n=100
g=10
a = sq.range(n)
a = a.withColumn('grp',F.floor(a['id']/g)*g)
a = a.withColumnRenamed('id','id_a')
b = sq.range(n)
b = b.withColumn('grp',F.floor(b['id']/g)*g)
b = b.withColumnRenamed('id','id_b')
c = a.join(b,(a.grp == b.grp) & (F.abs(a['id_a'] - b['id_b']) < 2)).drop(b['grp'])
c = c.sort('id_a')
c = c[['grp','id_a','id_b']]
c.explain() …Run Code Online (Sandbox Code Playgroud) 我正在重写Spark应用程序以使用更多DataFrame操作来提高效率和稳健性.但是,有一部分应用程序无法使用DataFrames完成,我必须放弃到RDD.剥离其基本要素,代码将如下所示:
C = A.join(B, join_key) # join_key is a string naming a column
D = C.rdd.mapPartitions(do_something)
Run Code Online (Sandbox Code Playgroud)
为了正确操作,do_something需要C.rdd进行分区join_key.我认为情况就是这样,因为equijoins通过按键对数据进行分区,然后形成键值相同的对.在Spark RDD连接中,对由迭代器在分区数据上隐式形成,并且除非我告诉Spark将迭代器"物化"到一个列表中,否则它们将无法离开它们被定义的分区.配对然后重新分配结果,我不在这里做.我希望DataFrame连接也是如此.
总而言之,上面的讨论并未证明确保了所需的分区.我依赖于通过API无法保证的Spark实现的细节,我不确定它是100%安全的.不能保证Catalyst优化器不会将额外的分区边界抛到一组共享相同密钥的对中,将其分解并使我的算法不正确.
为了确保所需的分区,我可以C.rdd.partitionBy(lambda x: x['join_key'])在应用我的do_something函数之前明确地做,但我担心这可能会触发大量不必要的序列化,混乱或其他开销.
DISTRIBUTE BY根据这篇博客文章,我似乎也可以使用HiveQL,但同样,我不知道这可能引发什么开销.
我的问题是:依赖连接引起的隐式分区是安全的,还是我应该明确地确定它?如果是这样,确保它的最有效方法是什么?我正在使用PySpark 1.6.2.
我想了解如何将表示表达式的字符串传递给dplyr,以便将字符串中提到的变量计算为数据帧中列的表达式.关于这个主题的主要内容包括传递,并且根本不讨论字符串.
很明显,在表示表达式时,quosures比字符串更安全,更清晰,所以当使用quosures时我们当然应该避免使用字符串.但是,在使用R生态系统之外的工具(例如javascript或YAML配置文件)时,通常需要使用字符串而不是quosures.
例如,假设我想要一个使用用户/调用者传入的表达式进行分组计数的函数.正如预期的那样,以下代码不起作用,因为dplyr使用非标准求值来解释参数group_by.
library(tidyverse)
group_by_and_tally <- function(data, groups) {
data %>%
group_by(groups) %>%
tally()
}
my_groups <- c('2 * cyl', 'am')
mtcars %>%
group_by_and_tally(my_groups)
#> Error in grouped_df_impl(data, unname(vars), drop): Column `groups` is unknown
Run Code Online (Sandbox Code Playgroud)
在dplyr 0.5中,我们将使用标准评估group_by_(.dots = groups)来处理这种情况.既然下划线动词已弃用,我们应该如何在dplyr 0.7中执行此类操作?
在只是列名的表达式的特殊情况下,我们可以使用这个问题的解决方案,但它们不适用于更复杂的表达式,例如2 * cyl不仅仅是列名.
根据联接值更新表时,Vertica具有有趣的更新语法。它不是使用联接来查找更新行,而是强制使用如下语法:
UPDATE a
SET col = b.val
where a.id = b.id
Run Code Online (Sandbox Code Playgroud)
(请注意,在这种情况下确实要强制使用此语法,因为在这种情况下,Vertica禁止我们使用包含“自我联接”的where子句,该子句是引用要更新的表的联接a。)
这种语法很好,但是与其他SQL方言相比,使用联接的方式不太明确。例如,在这种情况下会发生什么?
UPDATE a
SET col = CASE 0 if b.id IS NULL ELSE b.val END
where a.id = b.id
Run Code Online (Sandbox Code Playgroud)
a.id没有比赛时会发生什么b.id?难道a.col没有更新,就好像条件a.id = b.id所代表的内连接a和b?还是将其更新为零,就像条件是左外部联接一样?