Spark的dataframe转rdd通用工具类
需求解决问题
当每次读取hive表或者其他数据源,获取数据,相对其进行rdd操作,遇到任何类都需要df.rdd(row>row.getstring(0))去获取,就很麻烦,所以可以实现个通用的转换方式
1.dataframe转为rdd通用方法
/**
* df转为rdd 通用方法
*
* @param frame
* @return
*/
def dataFrameToRdd(frame: DataFrame): RDD[Array[Any]] = {
val fields: Array[StructField] = frame.schema.toArray
val zipData: Array[(StructField, Int)] = fields.zipWithIndex
val rdd: RDD[Array[Any]] = frame.rdd.map(row => {
val res: Array[Row => Any] = zipData.map(structField => squareRowkey2(structField._1, structField._2))
val array: Array[Any] = res.map(fun => {
val value = fun(row)
if (value == null) String.valueOf(value) else value
})
array
})
rdd
}
对类型进行判断
/**
* 根据schema信息进行判断与封装
*
* @param dataType
* @return
*/
//封装rowkey
def squareRowkey2(dataType: (StructField, Int)): (Row) => Any = {
val (structField, index) = dataType
structField.dataType match {
case StringType =>
(row: Row) => if (row.isNullAt(index)) null else row.getString(index)
case LongType =>
(row: Row) =>if (row.isNullAt(index)) null else row.getLong(index)
case FloatType =>
(row: Row) => if (row.isNullAt(index)) null else row.getFloat(index)
case DoubleType =>
(row: Row) => if (row.isNullAt(index)) null else row.getDouble(index)
case IntegerType =>
(row: Row) => if (row.isNullAt(index)) null else row.getInt(index)
case BooleanType =>
(row: Row) => if (row.isNullAt(index)) null else row.getBoolean(index)
case DateType =>
(row: Row) => if (row.isNullAt(index)) null else row.getDate(index)
case TimestampType =>
(row: Row) => if (row.isNullAt(index)) null else row.getTimestamp(index)
case BinaryType =>
(row: Row) => if (row.isNullAt(index)) null else row.getAs[Array[Byte]](index)
case ArrayType(elementType, containsNull) =>
(row: Row) => {
val value: mutable.WrappedArray[_ >: Integer with String <: io.Serializable with Comparable[_ >: Integer with String]] = elementType match {
case IntegerType => {
row.getAs[mutable.WrappedArray[Integer]](index)
}
case StringType => {
row.getAs[mutable.WrappedArray[String]](index)
}
case _ => row.getAs[mutable.WrappedArray[String]](index)
}
//这儿必须转换为java的list 防止map转json字符串不符合要求
if (value == null) {
util.Collections.emptyList()
}
JavaConversions.bufferAsJavaList(value.toBuffer)
}
case StructType(fields) =>
(row: Row) => row.getAs[mutable.Map[String, String]](index)
case _ =>
(row: Row) => row.getString(index)
}
}
二、rdd转实体对象
大多数是都是讲数据分装为case calss或者对象
def dataFrameToEntity [U: ClassTag] (frame: DataFrame, clazz: Class[U], hiveRdd: RDD[Array[Any]]) = {
val fields: Array[StructField] = frame.schema.toArray
val rdd = hiveRdd.map(array => {
val map = new util.HashMap[String, Any]()
fields.map(_.name).zip(array)
.foreach {
case (k, v) => (map.put(k, v))
}
val str = GsonUtil.toJsonString(map)
//这边转换工具类 就是gson的转为对象的方法
val value: U = GsonUtil.GsonToBean(str, clazz)
value
})
rdd
}
使用:
lazy val df: DataFrame =spark.read.table("user")
//将df转为rdd实体类
val userRdd: RDD[Array[Any]] = RddUtils.dataFrameToRdd(df)
val userRDD2: RDD[User] = RddUtils.dataFrameToEntity(df, classOf[User], userRdd)
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.TypeReference;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.reflect.TypeToken;
import org.apache.commons.lang3.StringUtils; import java.lang.reflect.Field;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map; /**
* @ClassName: com.xxx.sbc.dw.spark.submit.service.GsonUtil
* @Description: json工具类
* @Author: imp
* @Time: 2020/10/23 10:01
* @Version: 1.0
*/ public class GsonUtil { private static Gson gson = null; //判断gson对象是否存在了,不存在则创建对象
static {
if (gson == null) {
//gson = new Gson(); //当使用GsonBuilder方式时属性为空的时候输出来的json字符串是有键值key的,显示形式是"key":null,而直接new出来的就没有"key":null的
gson = new GsonBuilder().setDateFormat("yyyy-MM-dd HH:mm:ss").create();
}
} //无参的私有构造方法
private GsonUtil() {
} /**
* 将对象转成json格式
*
* @param object
* @return String
*/
public static String GsonString(Object object) {
String gsonString = null;
if (gson != null) {
gsonString = gson.toJson(object);
}
return gsonString;
} /**
* 将json转成特定的cls的对象
*
* @param gsonString
* @param cls
* @return
*/
public static <T> T GsonToBean(String gsonString, Class<T> cls) {
T t = null;
if (StringUtils.isNotEmpty(gsonString)) {
//传入json对象和对象类型,将json转成对象
t = JSONObject.parseObject(gsonString, cls);
}
return t;
} /**
* json字符串转成list
*
* @param gsonString
* @param cls
* @return
*/
public static <T> List<T> GsonToList(String gsonString, Class<T> cls) {
List<T> list = null;
if (gson != null) {
//根据泛型返回解析指定的类型,TypeToken<List<T>>{}.getType()获取返回类型
list = gson.fromJson(gsonString, new TypeToken<List<T>>() {
}.getType());
}
return list;
} /**
* json字符串转成list中有map的
*
* @param gsonString
* @return
*/
public static <T> List<Map<String, T>> GsonToListMaps(String gsonString) {
List<Map<String, T>> list = null;
if (gson != null) {
list = gson.fromJson(gsonString,
new TypeToken<List<Map<String, T>>>() {
}.getType());
}
return list;
} public static <T> List<Map<String, T>> gsonToListMaps(String str) {
List<Map<String, T>> list = null;
if (gson != null) {
list = gson.fromJson(str,
new TypeToken<List<Map<String, T>>>() {
}.getType());
}
return list;
} /**
* json字符串转成map的
*
* @param gsonString
* @return
*/
public static <T> Map<String, String> GsonToMaps(String gsonString) {
Map<String, String> map = null;
if (gson != null) {
map = gson.fromJson(gsonString, new TypeToken<Map<String, String>>() {
}.getType());
}
return map;
} /**
* 判断是否是json
*
* @param object
* @return
*/
public static Boolean isJson(Object object) {
try {
gson.toJson(object);
return true;
} catch (Exception e) {
System.err.format("{} is not json", object.toString());
return false;
}
} /**
* 对象转为json字符串
*
* @param o
* @return
*/
public static String toJsonString(Object o) {
return JSON.toJSONString(o, SerializerFeature.DisableCircularReferenceDetect);
} /**
* json转为map
*
* @param json
* @return
*/
public static Map<String, String> jsonToMap(String json) {
return JSON.parseObject(json, new TypeReference<LinkedHashMap<String, String>>() {
});
} public static Map<String, Object> entityToMap(Object obj) throws IllegalAccessException {
Map<String, Object> map = new LinkedHashMap<String, Object>();
Class<?> clazz = obj.getClass();
System.out.println(clazz);
for (Field field : clazz.getDeclaredFields()) {
field.setAccessible(true);
String fieldName = field.getName();
Object value = field.get(obj);
if (value == null) {
value = "";
}
map.put(fieldName, value);
}
return map;
}
Spark的dataframe转rdd通用工具类的更多相关文章
- spark下dataframe转为rdd格式
dataframe可以实现很多操作,但是存储到本地的时候,只能存 parquest格式 需要存储源格式,需要转换为rdd类型 将dataframe中的每一行都map成有逗号相连的string,就变为了 ...
- Spark SQL概念学习系列之DataFrame与RDD的区别
不多说,直接上干货! DataFrame的推出,让Spark具备了处理大规模结构化数据的能力,不仅比原有的RDD转化方式更加简单易用,而且获得了更高的计算性能.Spark能够轻松实现从MySQL到Da ...
- spark是怎么从RDD升级到DataFrame的?
本文始发于个人公众号:TechFlow,原创不易,求个关注 今天是spark专题的第五篇,我们来看看DataFrame. 用过Python做过机器学习的同学对Python当中pandas当中的Data ...
- [Spark][Python][RDD][DataFrame]从 RDD 构造 DataFrame 例子
[Spark][Python][RDD][DataFrame]从 RDD 构造 DataFrame 例子 from pyspark.sql.types import * schema = Struct ...
- [Spark][Python][DataFrame][RDD]DataFrame中抽取RDD例子
[Spark][Python][DataFrame][RDD]DataFrame中抽取RDD例子 sqlContext = HiveContext(sc) peopleDF = sqlContext. ...
- [Spark][Python][DataFrame][RDD]从DataFrame得到RDD的例子
[Spark][Python][DataFrame][RDD]从DataFrame得到RDD的例子 $ hdfs dfs -cat people.json {"name":&quo ...
- 【spark】dataframe常见操作
spark dataframe派生于RDD类,但是提供了非常强大的数据操作功能.当然主要对类SQL的支持. 在实际工作中会遇到这样的情况,主要是会进行两个数据集的筛选.合并,重新入库. 首先加载数据集 ...
- 小白学习Spark系列四:RDD踩坑总结(scala+spark2.1 sql常用方法)
初次尝试用 Spark+scala 完成项目的重构,由于两者之前都没接触过,所以边学边用的过程大多艰难.首先面临的是如何快速上手,然后是代码调优.性能调优.本章主要记录自己在项目中遇到的问题以及解决方 ...
- Spark 并行计算模型:RDD
Spark 允许用户为driver(或主节点)编写运行在计算集群上,并行处理数据的程序.在Spark中,它使用RDDs代表大型的数据集,RDDs是一组不可变的分布式的对象的集合,存储在executor ...
随机推荐
- pandas 移动列的方法
import pandas as pd df = pd.DataFrame(np.random.randn(3,4),columns=['a','b','c','d']) k = df.pop(&qu ...
- 写入到csv文件的两种方式(pd.DaaFrame 和 csv.writerow)
第一种: pd.DataFrame to_csv tmp = pd.DataFrame({"id":[str(i) for i in range(len(test_x))],f&q ...
- tensorflow 打印全部变量的一种方法
variable_names = [v.name for v in tf.all_variables()] values = sess.run(variable_names) for k,v in z ...
- Dell R740 使用U盘安装 CentOS7.4 出现Warning:dracut-initqueue timeout - starting timeout scripts解决办法
使用使用UltraISO软碟通刻录U盘,然后在Dell R740服务器安装CentOS7.4会出现如下错误: 解决办法: 1.使用blkid确认U盘的盘符,截图如下: 2.按F11键重启 3.进入启动 ...
- Linux文件权限问题
更改权限命令 chmod 常用参数 -R, --recursive change files and directories recursively (以递归的方式对目前目录下的所有档案与子目录进 ...
- 一、java多线程编程核心技术之(笔记)——多线程的实现
概念:可以理解为在进程中独立运行的子任务.比如,QQ.exe在运行时就有很多子任务在运行,好友视屏线程,下载文件线程,传输数据线程等等. 优点:1.提升CPU资源利用率,提升系统性能. 一.多线程的实 ...
- html文本域textarea高度自增、自动换行
文本域自动换行.高度自增,采用以下方式: html: <textarea rows="1" class="answerTextArea" maxlengt ...
- C#跳过工作日,计算几个工作日之后到期的方法
需求:消费者投诉企业,企业在2个工作日之内做出应答. 分析:1.工作日要刨去周末和法定节假日,而且每年的节假日不一样. 2.消费者可以在任意时间发起投诉,如果在非工作日发起了投诉,那么计算时间应该从工 ...
- js下 Day19、综合案例
一.吸顶楼层 效果图: 功能思路分析: 1. 面向对象框架 2. 渲染导航 \1. 数据 \2. 对象结构的数据用for in遍历 \3. 渲染时将属性名设为锚点(a标签的href) 3. 渲染车系 ...
- Numpy的学习5-array的分割
import numpy as np A = np.arange(12).reshape((3, 4)) print(A) """ array([[ 0, 1, 2, 3 ...