Java 如何在从数据集中选择列的不同值时保持数据的顺序
我有一个如下的数据集Java 如何在从数据集中选择列的不同值时保持数据的顺序,java,sql,apache-spark,apache-spark-sql,Java,Sql,Apache Spark,Apache Spark Sql,我有一个如下的数据集 +------+------+---------------+ | col1 | col2 | sum(costs) | +------+------+---------------+ | 1 | a | 3555204326.27 | | 4 | b | 22273491.72 | | 5 | c | 219175.00 | | 3 | a | 219175.00 | | 2 | c |
+------+------+---------------+
| col1 | col2 | sum(costs) |
+------+------+---------------+
| 1 | a | 3555204326.27 |
| 4 | b | 22273491.72 |
| 5 | c | 219175.00 |
| 3 | a | 219175.00 |
| 2 | c | 75341433.37 |
+------+------+---------------+
我需要选择col1的不同值,结果数据集的顺序应该是1、4、5、3、2(这些值在初始数据集中的可用顺序)。但秩序正在改变。有没有办法保持与初始数据集相同的顺序。Spark/SQL中的任何建议都可以
该数据集可通过spark中的以下顺序获得
df = sqlCtx.createDataFrame(
[(1, a, 355.27), (4, b, 222.98), (5, c, 275.00), (3, a, 25.00),
(2, c, 753.37)], ('Col1', 'col2', 'cost'));
您可以向数据库中添加一个索引列,然后在SQL请求中按id进行排序。我认为您需要重新格式化查询,并使用group BY而不是distinct,如下面的回答所示。您可以添加另一列,其中包含每行的索引,然后在“distinct”之后对该列进行排序。以下是一个例子:
import org.apache.spark.sql.functions._
val df = Seq(1, 4, 4, 5, 2)
.toDF("a")
.withColumn("id", monotonically_increasing_id())
df.show()
// +---+---+
// | a| id|
// +---+---+
// | 1| 0|
// | 4| 1|
// | 4| 2|
// | 5| 3|
// | 2| 4|
// +---+---+
df.dropDuplicates("a").sort("id").show()
// +---+---+
// | a| id|
// +---+---+
// | 1| 0|
// | 4| 1|
// | 5| 3|
// | 2| 4|
// +---+---+
请注意,要在1个特定列上执行distinct操作,可以使用
dropDuplicates
,如果要控制在重复情况下要采取的行,请使用groupBy
,,假设您尝试在col2
中远程复制(因为col1
中没有),以便最终结果为:
+----+----+---------------+
|col1|col2| sum|
+----+----+---------------+
| 1| a|3.55520432627E9|
| 4| b| 2.227349172E7|
| 5| c| 219175.0|
+----+----+---------------+
您可以添加一个索引列,如:
df = df.withColumn("__idx", monotonically_increasing_id());
然后执行所有需要的转换,然后将其删除,如:
df = df.dropDuplicates("col2").orderBy("__idx").drop("__idx");
这意味着你要:
步骤1:加载数据和内容:
+----+----+---------------+
|col1|col2| sum|
+----+----+---------------+
| 1| a|3.55520432627E9|
| 4| b| 2.227349172E7|
| 5| c| 219175.0|
| 3| a| 219175.0|
| 2| c| 7.534143337E7|
+----+----+---------------+
步骤2:添加索引:
+----+----+---------------+-----+
|col1|col2| sum|__idx|
+----+----+---------------+-----+
| 1| a|3.55520432627E9| 0|
| 4| b| 2.227349172E7| 1|
| 5| c| 219175.0| 2|
| 3| a| 219175.0| 3|
| 2| c| 7.534143337E7| 4|
+----+----+---------------+-----+
步骤3:转换(此处删除col2
中的DUP)并删除\uu idx
列:
+----+----+---------------+
|col1|col2| sum|
+----+----+---------------+
| 1| a|3.55520432627E9|
| 4| b| 2.227349172E7|
| 5| c| 219175.0|
+----+----+---------------+
Java代码可以是:
package net.jgp.books.spark.ch12.lab990_others;
import static org.apache.spark.sql.functions.monotonically_increasing_id;
import java.util.ArrayList;
import java.util.List;
import org.apache.spark.sql.Dataset;
import org.apache.spark.sql.Row;
import org.apache.spark.sql.RowFactory;
import org.apache.spark.sql.SparkSession;
import org.apache.spark.sql.types.DataTypes;
import org.apache.spark.sql.types.StructField;
import org.apache.spark.sql.types.StructType;
/**
* Keeping the order of rows during transformations.
*
* @author jgp
*/
public class KeepingOrderApp {
/**
* main() is your entry point to the application.
*
* @param args
*/
public static void main(String[] args) {
KeepingOrderApp app = new KeepingOrderApp();
app.start();
}
/**
* The processing code.
*/
private void start() {
// Creates a session on a local master
SparkSession spark = SparkSession.builder()
.appName("Splitting a dataframe to collect it")
.master("local")
.getOrCreate();
Dataset<Row> df = createDataframe(spark);
df.show();
df = df.withColumn("__idx", monotonically_increasing_id());
df.show();
df = df.dropDuplicates("col2").orderBy("__idx").drop("__idx");
df.show();
}
private static Dataset<Row> createDataframe(SparkSession spark) {
StructType schema = DataTypes.createStructType(new StructField[] {
DataTypes.createStructField(
"col1",
DataTypes.IntegerType,
false),
DataTypes.createStructField(
"col2",
DataTypes.StringType,
false),
DataTypes.createStructField(
"sum",
DataTypes.DoubleType,
false) });
List<Row> rows = new ArrayList<>();
rows.add(RowFactory.create(1, "a", 3555204326.27));
rows.add(RowFactory.create(4, "b", 22273491.72));
rows.add(RowFactory.create(5, "c", 219175.0));
rows.add(RowFactory.create(3, "a", 219175.0));
rows.add(RowFactory.create(2, "c", 75341433.37));
return spark.createDataFrame(rows, schema);
}
}
package net.jgp.books.spark.ch12.lab990_其他;
导入静态org.apache.spark.sql.functions.monotional\u递增\u id;
导入java.util.ArrayList;
导入java.util.List;
导入org.apache.spark.sql.Dataset;
导入org.apache.spark.sql.Row;
导入org.apache.spark.sql.RowFactory;
导入org.apache.spark.sql.SparkSession;
导入org.apache.spark.sql.types.DataTypes;
导入org.apache.spark.sql.types.StructField;
导入org.apache.spark.sql.types.StructType;
/**
*在转换期间保持行的顺序。
*
*@author jgp
*/
公共类KeepingOrderApp{
/**
*main()是应用程序的入口点。
*
*@param args
*/
公共静态void main(字符串[]args){
KeepingOrderApp=新建KeepingOrderApp();
app.start();
}
/**
*处理代码。
*/
私有void start(){
//在本地主机上创建会话
SparkSession spark=SparkSession.builder()
.appName(“拆分数据帧以收集它”)
.master(“本地”)
.getOrCreate();
数据集df=createDataframe(spark);
df.show();
df=df.withColumn(“\uuuidx”,单调递增的\uid());
df.show();
df=df.dropDuplicates(“col2”).orderBy(“\uuuidx”).drop(“\uuuidx”);
df.show();
}
专用静态数据集createDataframe(SparkSession spark){
StructType架构=数据类型。createStructType(新的StructField[]{
DataTypes.createStructField(
“col1”,
DataTypes.IntegerType,
假),,
DataTypes.createStructField(
“col2”,
DataTypes.StringType,
假),,
DataTypes.createStructField(
“总和”,
DataTypes.DoubleType,
假)});
列表行=新建ArrayList();
添加(RowFactory.create(1,“a”,3555204326.27));
添加(RowFactory.create(4,“b”,22273491.72));
添加(RowFactory.create(5,“c”,219175.0));
添加(RowFactory.create(3,“a”,219175.0));
添加(RowFactory.create(2,“c”,75341433.37));
返回spark.createDataFrame(行,模式);
}
}
如果数据来源是不可变的,以及您使用的Spark版本是什么,您可以在问题中添加数据来源(CSV、数据库)吗。。。