基本问题:
我想将Spark数据帧**
的“第一行”复制到另一个Spark数据帧sdf
。
我不明白下面的代码出了什么问题。 因此,我期待着一个解决方案和一个解释,在我的最小示例中失败了。
一个最小的示例:
sdfEmpty
// create a spark data frame
import org.apache.spark.sql._
val sdf = Seq(
(1, "a"),
(12, "b"),
(234, "b")
).toDF("A", "B")
sdf.show()
+---+---+
| A| B|
+---+---+
| 1| a|
| 2| b|
| 3| b|
+---+---+
// create an empty spark data frame to store the row
// declare it as var, such that I can change it later
var sdfEmpty = spark.createDataFrame(sc.emptyRDD[Row], sdf.schema)
sdfEmpty.show()
+---+---+
| A| B|
+---+---+
+---+---+
// take the "first" row of sdf as a spark data frame
val row = sdf.limit(1)
// combine the two spark data frames
sdfEmpty = sdfEmpty.union(row)
为:
row
row.show()
+---+---+
| A| B|
+---+---+
| 1| a|
+---+---+
的预期结果是:
sdfEmpty
但是我得到了:
+---+---+
| A| B|
+---+---+
| 1| a|
+---+---+
问题: 我感到困惑的是:使用val row = sdf.limit(1)我以为我创建了一个永久性/不可更改/定义明确的对象。这样,当我打印一次并将其添加到某物时,我得到的结果相同。
备注:(非常感谢Daniel的评论)
我知道在scala的分布式世界中,没有明确定义的“第一行”概念。我把它放在这里是为了简单起见,我希望那些挣扎于类似事物的人们会“偶然地”使用“第一”一词。
我尝试实现的目标如下:(在一个简化的示例中) 我有一个带有2列A和B列的数据框。A列部分排序,B列完全排序。 我想过滤数据列。因此,这种想法是一种分而治之:将数据帧分割成两列,然后将它们完全按照顺序进行过滤,然后再进行过滤。 (并进行明显的迭代)
要实现这一点,我需要选择一个定义明确的行,并将日期拆分为w.r.t。行但是,如最小的示例所示,我的命令没有产生定义明确的对象。
非常感谢
答案 0 :(得分:1)
火花是分布式的,因此“第一”的概念不是我们可以依靠的。根据分区的不同,调用limit
或first
时会得到不同的结果。
要获得一致的结果,您的数据必须具有我们可以使用的基本顺序-这很有意义,因为除非对您的数据进行逻辑排序,否则我们无法真正说出采用第一行。
假设要相对于A列采用第一行,只需运行orderBy("A").first()
(*)即可。尽管如果A列包含多个具有相同最小值的行,则无法保证将获得哪一行。
(**我假设scala API与Python的命名相同,所以如果它们的名称不同,请更正我的意思)
答案 1 :(得分:0)
@Christian,您可以通过使用take函数来实现此结果。 take(num)取RDD的前num个元素。它的工作方式是先扫描一个分区,然后使用该分区的结果来估算满足限制所需的其他分区的数量。
这里是代码段。
scala> import org.apache.spark.sql.types._
scala> val sdf = Seq(
(1, "a"),
(12, "b"),
(234, "b")
).toDF("A", "B")
scala> import org.apache.spark.sql._
scala> var sdfEmpty = spark.createDataFrame(sc.emptyRDD[Row], sdf.schema)
scala> var first1 =sdf.rdd.take(1)
scala> val first_row = spark.createDataFrame(sc.parallelize(first1), sdf.schema)
scala> sdfEmpty.union(first_row).show
+---+---+
| A| B|
+---+---+
| 1| a|
+---+---+
有关take()和first()函数的更多信息,请阅读spark Documentation。如果您有与此相关的任何查询,请告诉我。
答案 2 :(得分:0)
我正在发布此答案,因为它包含丹尼尔(Daniel)建议的解决方案。一旦我浏览了通过mahesh gupta提供的文献或进行了更多测试,我将更新此答案并评论“现实生活”中不同方法的运行时。
基本问题:
我想将Spark数据帧@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View root = inflater.inflate(R.layout.activity_bottom_fragment, container, false);
return root;
}
@Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
BottomNavigationView navView = root.findViewById(R.id.nav_view);
AppBarConfiguration appBarConfiguration = new AppBarConfiguration.Builder(
R.id.navigation_home, R.id.navigation_dashboard, R.id.navigation_notifications)
.build();
NavController navController = Navigation.findNavController(activity, R.id.nav_host_fragment);//error here
NavigationUI.setupActionBarWithNavController((AppCompatActivity) activity, navController, appBarConfiguration);
NavigationUI.setupWithNavController(navView, navController);
}
的“第一行”复制到另一个Spark数据帧sdf
。
就像在火花的分布式世界中一样,首先没有一个明确的概念,但是由于sdfEmpty
可以实现类似的目的。
一个最小的工作示例:
orderBy
// create a spark data frame
import org.apache.spark.sql._
val sdf = Seq(
(1, "a"),
(12, "b"),
(234, "b")
).toDF("A", "B")
sdf.show()
+---+---+
| A| B|
+---+---+
| 1| a|
| 2| b|
| 3| b|
+---+---+
// create an empty spark data frame to store the row
// declare it as var, such that I can change it later
var sdfEmpty = spark.createDataFrame(sc.emptyRDD[Row], sdf.schema)
sdfEmpty.show()
+---+---+
| A| B|
+---+---+
+---+---+
// take the "first" row of sdf as a spark data frame
val row = sdf.limit(1).collect()
// combine the two spark data frames
sdfEmpty = sdfEmpty.union(row)
是:
row
**,row.show()
+---+---+
| A| B|
+---+---+
| 1| a|
+---+---+
的结果是:**
sdfEmpty
备注:Daniel给出的解释(请参见上面的评论)+---+---+
| A| B|
+---+---+
| 1| a|
+---+---+
是一种转换-在运行诸如show或collect之类的操作之前,不会对其进行评估。因此,根据上下文,它可以返回不同的值。要始终使用.limit(n)
的结果,可以将.limit
的结果用于驱动程序并将其用作局部变量。