背景:最近帮别人写了2个pyspark的代码以及帮别人安装环境,在做的过程中碰到很多的困难。所以想把这些困难做个总结。
问题总结:
1,由于客户需要交付的是ipynb文件,所以需要在jupyter上写pyspark程序。所以问题是jupyter怎么加载pyspark包?
2,客户提供的是一个json文档数据集,json中有很多的array数据集,当这些array数据通过spark读入dataframe时,要怎么对这些数据进行延展平铺?
3,怎么把dataframe的数据转成list
4,怎么做python 多维分析的可视化操作
5,有很多的环境时不能连互联网的,那么碰到命令不能够使用要怎么处理
问题解决:
问题一解决
在命令行中执行以下命令就可以。
PYSPARK_DRIVER_PYTHON=jupyter PYSPARK_DRIVER_PYTHON_OPTS='notebook' /Users/xxxxx/Downloads/spark/bin/pyspark
问题二解决
当我们想到数据列转行时,我门一开始想到的是 hive 的 lateral view explode,想到pyspark.sql.function 包中的explode。但是当有多个字段需要平铺,并且不能够让数据翻倍时,意思是每个array中的数据是一一对应的的。那要怎么处理。代码如下:
#对海拔字段altitude进行列转行,并添加一个序号列pos,形成dataframe df1
df1=df.filter(col("userId").isNotNull()).select("id","userId","gender","sport","url",posexplode("altitude").alias("pos","altitude"))
#对心率字段heart_rate进行列转行,并添加一个序号列pos,形成dataframe df2
df2=df.filter(col("userId").isNotNull()).select("id",posexplode("heart_rate").alias("pos","heart_rate"))
#对维度字段latitude进行列转行,并添加一个序号列pos,形成dataframe df3
df3=df.filter(col("userId").isNotNull()).select("id",posexplode("latitude").alias("pos","latitude"))
#对经度字段longitude进行列转行,并添加一个序号列pos,形成dataframe df4
df4=df.filter(col("userId").isNotNull()).select("id",posexplode("longitude").alias("pos","longitude"))
#对时间字段timestamp进行列转行,并添加一个序号列pos,
#把源中的unix timestamp转换为标准格式的timestamp类型并命名为 timestamp
#通过上面转换的timestamp字段进行抽取年月日,命名day
#通过上面转换的timestamp字段进行抽取小时,命名hour
#形成dataframe df5
df5=df.filter(col("userId").isNotNull()).select("id",posexplode("timestamp").alias("pos","timestamp"))\
.withColumn("timestamp",concat_ws(".",from_unixtime(substring(col("timestamp"),0,10),"yyyy-MM-dd HH:mm:ss"),substring(col("timestamp"),-3,3)))\
.withColumn("day",substring(col("timestamp"),0,10))\
.withColumn("hour",substring(col("timestamp"),12,2))
#对速度字段speed进行列转行,并添加一个序号列pos,形成dataframe df6
df6=df.filter(col("userId").isNotNull()).select("id",posexplode("speed").alias("pos","speed"))
#把上面所有的dataframe数据集进行join形成 源文件的dataframe数据集,join的条件是id 和 pos
df_all=df1.join(df2,on=["id","pos"],how='inner').drop(df2.pos)\
.join(df3,on=['id','pos'],how='inner').drop(df3.pos)\
.join(df4,on=['id','pos'],how='inner').drop(df4.pos)\
.join(df5,on=['id','pos'],how='inner').drop(df5.pos)\
.join(df6,on=['id','pos'],how='inner').drop(df6.pos)
之前也尝试过对每一个array数据进行explode,后来发现在pyspark中不能够在一个dataframe中同时使用2次及以上explode,因为这样会让数据翻倍,内存吃紧。这里花了很长时间
问题三解决
通过把df 转成rdd,之后collect()
df = df.rdd.flatMap(lambda x: x).collect()
问题四解决
问题四现在还没完全解决,我只做了一维的散点图,没有做多维的散点图
altitude_list=df_correlation.filter(col("time")=="morning").filter(substring(col("day"),0,4)=="2015").select("altitude").rdd.flatMap(lambda x:x).collect()
x=np.array(altitude_list)
heart_list=df_correlation.filter(col("time")=="morning").filter(substring(col("day"),0,4)=="2015").select("heart_rate").rdd.flatMap(lambda x:x).collect()
y=np.array(heart_list)
s=(20*np.random.rand(len(heart_list))**2)
plt.figure(figsize=(10,10))
plt.xlabel('altitude')
plt.ylabel('heart_rate')
plt.scatter(x,y,s)
plt.show()
问题五 没有解决
场景是,有很多机构的虚拟机环境出于对安全考虑不会连接互联网,那么就会出现某些命令不能够使用的情况,当时一直在纠结互联网的问题,后来才清楚可以去另外的一台连了互联网的linux虚拟机环境下载一个rpm安装包,之后上传到此虚拟机,直接通过yum安装就行
yum install -y yum-plugin-downloadonly
yum --hlp #查看yum是否有 --downloadonly
mkdir /opt/bunzip
yum install bunzip2 --downloadonly --downloaddir=/opt/bunzip
进入/opt/bunzip 帮忙把bunzip2_xx.rpm的安装包发一下