Spark scala中将Array(Row)转化为DataFrame(另一种抽样方式)

1.spark DataFrame常规的采样方式——sample()

由于scala中 对DataFrame 方式为 sample() 方法

sample : 采样
采样变换根据给定的随机种子,从RDD中随机地按指定比例选一部分记录,创建新的RDD。采样变换 在机器学习中可用于进行交叉验证。
语法
def sample(withReplacement: Boolean, fraction: Double, seed: Long = Utils.random.nextLong): RDD[T]

参数
withReplacement : Boolean , True表示进行替换采样,False表示进行非替换采样
fraction : Double, 在0~1之间的一个浮点值,表示要采样的记录在全体记录中的比例
seed :随机种子


var sample_frac = (extract_nums/result_data.count().toFloat).formatted("%.2f").toFloat
result_data_sample = result_data.sample(false, sample_frac)

这样就有问题 :
1.当sample_frac采样率✖️数据总条数 出现小数时 采样数据总条数未必等于例子中的extract_nums(采样条数)
2.当采样率过小 或者 采样率*数据总条数<1 时 采样数据为空

所以今天介绍一种全新的采样方式,可以采样出等于extract_nums(采样条数) 的数据

利用take(n)构造Row进而构造DataFrame(相对比较复杂)

take:无序采样
使用take成员函数获得指定数量的记录,返回一个数组。与top不同,take在提取记录 前不进行排序,它仅仅逐分区地提取够指定数量的记录就返回结果。可以将take方法 视为对RDD对象的无序采样。
语法
def take(num: Int): Array[T]
参数 num : Int , 要获取的记录数量
返回值
包含指定数量记录的数组,记录类型为T。

代码如下:

import spark.implicits._

var data3 = Seq(
  (null, "2002", "196", "1", "bai"),
  (null, "4004", "192", "2", "wang"),
  (null, "9009", "126", "1", "bai"),
  (null, "9009", "126", "5", "wei"),
  ("1","10010", "19219", "5", "wei")
).toDF("label", "AMOUNT", "Pclass", "nums", "name")
import org.apache.spark.sql.functions._
data3 = data3.withColumn("AMOUNT", col("AMOUNT").cast("int"))
data3.show()
+-----+------+------+----+----+
|label|AMOUNT|Pclass|nums|name|
+-----+------+------+----+----+
| null|  2002|   196|   1| bai|
| null|  4004|   192|   2|wang|
| null|  9009|   126|   1| bai|
| null|  9009|   126|   5| wei|
|    1| 10010| 19219|   5| wei|
+-----+------+------+----+----+

//查看data3各列数据类型
data3.dtypes.toMap

res835: scala.collection.immutable.Map[String,String] = Map(name -> StringType, label -> StringType, Pclass -> StringType, AMOUNT -> IntegerType, nums -> StringType)

//使用take抽取3条 并转化为Seq 只有Seq才能构建DataFrame
var rdd = sc.parallelize(data3.take(3).toSeq)

//重新构建 DataFrame表结构 与原表对应 名称可以不同  但是对应类型必须相同  这就是前面看原表类型的原因
val schema = new StructType().add(StructField("label", StringType, true)).add(StructField("AMOUNT",  IntegerType, true)).add(StructField("Pclass", StringType, true)).add(StructField("nums",StringType, true)).add(StructField("name", StringType, true))


val df = spark.createDataFrame(rdd, schema)
df.show()

+-----+------+------+----+----+
|label|AMOUNT|Pclass|nums|name|
+-----+------+------+----+----+
| null|  2002|   196|   1| bai|
| null|  4004|   192|   2|wang|
| null|  9009|   126|   1| bai|
+-----+------+------+----+----+

注:如果某列全为null 空 类型设置为 NullType

涉及到Row构造DataFrame知识参考:
https://www.itranslater.com/qa/details/2325684091590542336

你可能感兴趣的:(DateFrame,Scala,Spark)