参考https://blog.csdn.net/xufangfang5206/article/details/80030300
https://www.cnblogs.com/ruoniao/p/6869319.html
split是可以用多种不同的符号(转义字符,以及标点符号)作为分隔符的!!!
(1)读取txt文件,按\t分隔,将分割出来的列大于指定列的滤掉,解析不准;
注意len的用法
self.df_judgedoc_info_sample = self.session.read.text(self.judgedoc_info_sample_table_input)
self.df_judgedoc_info_sample = self.df_judgedoc_info_sample.rdd \
.filter(lambda line: len((line["value"] or "").split('\t')) == 6)\
.map(lambda line: Row(**dict(zip(raw_judgedoc_info_field, line["value"].split('\t')))))\
.toDF()
(a) 注意此处len的写法,为了避免有的时候变量为空,需增加一个 or '' ,构成逻辑变量,为空会自动取 '' ,len('')为0,这样就不会报错;
In[38]: len('哈哈' or '')
Out[38]: 6
In[39]: len( None or '')
Out[39]: 0
In[40]: len( None)
Traceback (most recent call last):
File "/usr/lib/python2.7/dist-packages/IPython/core/interactiveshell.py", line 2820, in run_code
exec code_obj in self.user_global_ns, self.user_ns
File "" , line 1, in
len( None)
TypeError: object of type 'NoneType' has no len()
(b)filter(lambda line: len((line["value"] or "").split('\t'))== 6)
结构解读顺序:
首先:(line["value"] or "").split('\t')
先取line中的value字段列,spark读txt文件的时候默认的列是value命名的,txt存文件是一行一行地存,默认不分列,因此,当存一些包含汉字字段的时候,不需要像csv一样把一行还要解析成多列,有时候解析不准,会出现IndexOutBound,索引越界的错误,即误解析了无穷列,超出了spark处理列的范围;因此可以用txt保存,然后用读txt的方式处理字段;取split
用\t划分
In[56]: u'哈哈 你好 哼哼'.split(u'\t')
Out[56]: [u'\u54c8\u54c8 \u4f60\u597d \u54fc\u54fc']
用空格划分
In[57]: u'哈哈 你好 哼哼'.split(u' ')
Out[57]: [u'\u54c8\u54c8', u'\u4f60\u597d', u'', u'', u'\u54fc\u54fc']
In[51]: S = "this is string example....wow!!!"
In[52]: print (S.split( ))
['this', 'is', 'string', 'example....wow!!!']
In[53]: print (S.split('i',1))
['th', 's is string example....wow!!!']
In[54]: print (S.split('w'))
['this is string example....', 'o', '!!!']
In[55]: '哈哈 你好 哼哼'.split(u'\t')
str = "Line1-abcdef \nLine2-abc \nLine4-abcd";
print str.split( );
print str.split(' ', 1 );
结果:
['Line1-abcdef', 'Line2-abc', 'Line4-abcd']
['Line1-abcdef', '\nLine2-abc \nLine4-abcd']
上式中1为分隔次数;split还可以指定分隔次数;
split('符号'),其作用就是,找到字符串中该符号的位置,在该符号的位置加上 ',' 这样就达到用以分隔前后字符的目的, 然后删除该符号本身!!!!
然后:
理解filter的作用:
filter本质是作用一个bool值,即里面的函数返回的是一个bool变量:
filter(lambda line: len((line["value"] or "").split('\t'))== 6) 正确
里面的lambda line: len((line["value"] or "").split('\t'))== 6 ,判断列数为6返回true,否则返回False;
错误写法:
filter(lambda line: line.split('\t') if len(line.split('\t')) <7 else None)
这会出现两个bug:第一),line为空;第二)lambda函数返回的有None值不为True 和False,filter只接受true和False;
字符串的分隔
字符串的切割
当需要的分隔符是一个是:
s.split("分隔符")
当分隔符是多个时:
s = "abcd,1313|;gg2*hhh"
方法一:
将多个分隔符每个每个的拆开分隔
方法二:
通过re模块的split()方法
方法一:
1 def mySplit(s,ds):
2 res =[s]
3 for d in ds:
4 t =[]
5 map(lambda x:t.extend(x.split(d)),res)
6 res = t
7 #当s中存在连续的分隔符时,就会出现空格的,下面是去除空格
8 return [x for x in res if x]
9 s = "abcd,1313|;gg2*hhh"
10 res = ',|;*'
11 print(mySplit(s,res))
方法二:
1 In [9]: s = "abcd,1313|;gg2*hhh"
2
3 In [10]: import re
4
5 In [11]: re.split('[,|;*]+',s) #正则表达式[,|;*]中的任何一个出现至少一次
6 Out[11]: ['abcd', '1313', 'gg2', 'hhh']
注意map的用法
dfrdd = df.map(mapper)
dfrdd = df.map(lambda line:mapper(line))
sqlContext = SQLContext(sparkContext=sc)
df = sqlContext.read.text(hdfspath)
dfrdd = df.map(mapper)
此处df的结构为'pyspark.rdd.RDD'>
有的时候,map需要写lambda,有的时候不需要,依据是判断当前函数的输入是不是可以直接用rdd的结构进行输入,rdd的结构与
dfrdd = df.map(mapper)
print(type(dfrdd)) #
Dataframe转RDD
RDD.map(func)
RDD.map(lambda x : func(x))
上面两个的区别;数据结构不一样?????
piplineRDD has no map
数值和键值对RDD
数字类型的RDD支持统计型函数操作,而键值对形式的RDD诸如根据键聚合的数据的键值对操作
把一个普通的RDD转化为pairRDD,可调用map函数实现,pairRDD
ps aux | grep spark
kill 155286
RDD is empty filter本来