在clojure中实现flambo mapValues函数

在clojure中实现flambo mapValues函数,clojure,apache-spark,rdd,flambo,Clojure,Apache Spark,Rdd,Flambo,我有一个clojure函数,它使用flambo v0.60函数api对样本数据集进行一些分析。我注意到,当我使用(getrdd2)而不是获取rdd集合中的第二个元素时,它获取rdd集合中第一个元素的第二个字符。我的假设是clojure将rdd集合中的每一行视为一个完整的字符串,而不是一个向量,这样我就可以获得集合中的第二个元素。我正在考虑使用map values函数将映射值转换为向量,我可以得到第二个元素,我尝试了以下方法: (defn split-on-tab-transformation [

我有一个clojure函数,它使用flambo v0.60函数api对样本数据集进行一些分析。我注意到,当我使用
(getrdd2)
而不是获取rdd集合中的第二个元素时,它获取rdd集合中第一个元素的第二个字符。我的假设是clojure将rdd集合中的每一行视为一个完整的字符串,而不是一个向量,这样我就可以获得集合中的第二个元素。我正在考虑使用map values函数将映射值转换为向量,我可以得到第二个元素,我尝试了以下方法:

(defn split-on-tab-transformation [xctx input]
 (assoc xctx :rdd (-> (:rdd xctx)
                   (spark/map (spark/fn [row] (s/split row #"\t")))
                   (spark/map-values vec)))) 
不幸的是,我犯了一个错误:
java.lang.IllegalArgumentException:找不到匹配的方法:org.apache.spark.api.java.JavaRDD类的mapValues…

这是返回rdd中第一个集合的代码: (假设我在上述函数中删除了
(火花/贴图值vec)

(defn get-distinct-column-val
 "input = {:col val}"
  [ xctx input ]
  (let [rdds (-> (:rdd xctx)
           (f/map (f/fn [row] row))
           f/first)]
(clojure.pprint/pprint rdds)))
输出:

[2.00000 770127      200939.000000   \t6094\tBENTONVILLE, AR DPS\t22.500000\t5.000000\t2.500000\t5.000000\t0.000000\t0.000000\t0.000000\t0.000000\t0.000000\t1\tStore Tab\t0.000000\t4.50\t3.83\t5.00\t0.000000\t0.000000\t0.000000\t0.000000\t19.150000]
如果我尝试获取第二个元素
770127

(defn get-distinct-column-val
 "input = {:col val}"
  [ xctx input ]
  (let [rdds (-> (:rdd xctx)
           (f/map (f/fn [row] row))
           f/first)]
   (clojure.pprint/pprint (get rdds 1)))
我得到:

[\.]


我是clojure新手,非常感谢您的帮助。首先,感谢
map values
(或Spark API中的
map values
)仅在PairRDD上是有效的转换(例如类似以下内容
[:foo[1 2 3]]
.rdd的值可以解释为某种映射,其中第一个元素是键,第二个元素是值

如果您有像这样的RDD
mapValues
在不更改键的情况下转换值。在这种情况下,您应该使用第二个映射,尽管它似乎已过时,因为
clojure.string/split
已返回向量

使用
映射值的一个简单示例

(让[pairs[(ft/tuple:foo 1)(ft/tuple:bar 2)]
rdd(f/parallelize pairs sc pairs);;注意parallelize pairs->PairRDD
结果(->rdd
(f/地图价值公司);地图价值
(f/收集)]
(断言(=结果[(英尺/元组:foo 2)(英尺/元组:bar 3)])
从您的描述来看,您使用的是一个输入RDD,而不是从选项卡转换时的拆分返回的RDD。如果我不得不猜测您试图使用的是原始的
xctx
,而不是从选项卡转换时的拆分返回的RDD。因为Clojure
映射
是不可变的
assoc
不可更改更改已传递的参数并
get distinct column val
receives
RDD[String]
not
RDD[Array[String]

基于命名约定,我假设您希望为数组中的单个位置获取不同的值。为了清晰起见,我删除了代码中未使用的部分。首先,让我们创建虚拟数据:

(spit“data.txt”
(str“马自达RX4\t21\t6\t160\n”
“马自达RX4 Wag\t21\t6\t160\n”
“Datsun 710\t22.8\t4\t108\n”))
添加函数的重写版本

(选项卡转换时的defn拆分[xctx]
(assoc xctx:rdd(->)(:rdd xctx)
(f/map#(clojure.string/split%#“\t“#”)))
(defn获取不同的列val
[xctx col]
(->)(:rdd xctx)
(f/map#(获取%col))
(f(b)
和结果

(断言)
(=#{“马自达RX4 Wag”“Datsun 710”“马自达RX4”}
(->{:sc:rdd(f/text文件sc“data.txt”)}
(选项卡转换时拆分)
(获取不同的列值0)
(f/收取)
(集)

@noisesmith你能帮我解决这个问题吗challenge@cbbetz你能帮我解决这个flambo和clojure问题吗谢谢。我是否可以在不使用
assoc
的情况下用rdd上的
最新的
转换来更新
:rdd
,或者
assoc
正在运行使用转换中的值更新
:rdd
键。实际上,您对这个问题的假设是正确的。我非常感谢您的帮助..我只想澄清一下
assoc
clojure函数。clojure数据结构是不可变的,因此实际上没有更新这样的事情。您总是会得到一个新的数据一个结构。你可以把
xctx
变成一个并使用
swap!
但我怀疑这是个好主意。像上面这样捕获一个输出是一个更干净的解决方案,可以确保引用的透明性。顺便说一句,如果你喜欢答案,我不介意向上投票:-)示例中还有一个问题,
split on tab transformation
是否会更改
:rdd
键在
xctx
中的值,这样当
get distinct column val
在xctx中使用
:rdd
键时,它实际上会使用
split on tab transformation
中的新值,而不是它以前的值?ThanksecxActly.
在选项卡转换时拆分
返回
assoc
的结果,这是一个新映射,
:rdd
等于
(:rdd xctx)…)
并将其传递到
get distinct column val
。使用可变状态会给代码增加一个全新的复杂性。因此,在我看来,基本问题是它是否真的值得。一般来说,我会说它不值得。我不确定您首先为什么需要
xctx
。我没有使用它的经验
flambo
(今天第一次)和Clojure(除非你算上一些玩具项目),但说到Spark,简单地传递RDD是很自然的。因为RDD和转换只是一个配方,它是一种轻量级的方法,使程序的推理变得更容易。