我有以下地图:
CREATE DIRECTORY test_dir AS 'C:\';
GRANT READ, WRITE ON DIRECTORY test_dir TO exporter;
基本上,当某人的HR低于60时,它被归类为休息,110以上被归类为运动。元组的第二个变量表示该人已经做了10分钟。
现在Rigth,这会为60到110之间的值映射一个空键。我想要的是完全丢弃它们。这怎么可以实现?
所以来自
val pairs = lines.map( l => ( if (l.split(",")(1).toInt < 60) { "rest" } else if (l.split(",")(1).toInt > 110) { "sport" }, 10) ).reduceByKeyAndWindow((a:Int, b:Int) => (a+b), Seconds(12))
我正在尝试过滤掉("rest", 30)
("sport", 120)
((),10)
。
我试过了
((),10)
似乎无效。
答案 0 :(得分:1)
您的问题是,if
表达式会在String
与{1}}匹配时返回Unit
。您可以轻松修复filter
:
val pairs = lines.map(
l => (if (l.split(",")(1).toInt < 60) {"rest"} else if (l.split(",")(1).toInt > 110) {"sport"}, 10))
.filter(_._1 != ())
scala中的 ()
是Unit
类型的标识。
但这不是正确的方法,真的。结果仍然会得到(Unit, Int)
的元组。您使用此if
语句丢失了类型。
正确的方法是先过滤您的数据并详尽if
:
val pairs =
lines.map(_.split(",")(1).toInt)
.filter(hr => hr < 60 || hr > 110)
.map(hr => (if (hr < 60) "rest" else "sport", 10))
或使用collect
.filter.map
中的val pairs =
lines.map(_.split(",")(1).toInt)
.collect{
case hr if hr < 60 => "rest" -> 10
case hr if hr > 110 => "sport" -> 10
}
:
split
这个变体可能更具可读性。
另外,请注意我如何将split
移到单独的步骤中。这样做是为了避免第二次调用flatMap
第二次if。
<强> UPD 即可。另一种方法是使用val pairs =
lines.flatMap(_.split(",")(1).toInt match{
case hr if hr < 60 => Some("rest" -> 10)
case hr if hr > 110 => Some("sport" -> 10)
case _ => None
})
,如评论中所示:
filter
它可能会或可能不会更有效率,因为它可以避免Option
步骤,但会在INT_MAX
中添加包装和展开元素。您可以测试不同方法的表现并告诉我们结果。
答案 1 :(得分:0)
注意:不是这个问题的直接答案。但它对使用数据帧的用户可能有用
在Dataframe中,我们可以使用drop函数删除不包含指定列值的行
在这种情况下,您可以使用sc.parallelize和toDF来构造数据帧。然后你可以使用df.drop()