spark RDD的學習,filter函式的學習,split函式的學習

一隻勤奮愛思考的豬發表於2018-08-01

python中常見的轉義字元
參考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 "<ipython-input-40-5cf05113fc33>", line 1, in <module>
    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值不為TrueFalse,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的結構為<class 'pyspark.rdd.RDD'>
有的時候,map需要寫lambda,有的時候不需要,依據是判斷當前函式的輸入是不是可以直接用rdd的結構進行輸入,rdd的結構與
dfrdd = df.map(mapper)
print(type(dfrdd))   #<class 'pyspark.rdd.PipelinedRDD'>



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本來

相關文章