Pandas 第7章 文本數據

目錄

string 類型的性值

拆分和拼接

替換

子串匹配與提取

常用字符串方法

問題與練習


  1. string 類型的性值
    1. string 與object區別
      1. 字符存取方法,string返回相應數據的Nullable類型,object會因缺失值存在而改變返回類型;
      2. 某些Series方法不能再string上使用,Series.str.decode()  因爲存儲的是字符串而不是字節
      3. string類型在缺失值存儲或運算時,類型廣播時pd.NAN,而不是np.nan
    2. string類型的轉化
      1. 將其他類型的數據直接轉化爲string可能會出錯,辦法如下
        s=pd.Series([1,1.])
        print(s)
        s.astype('string')
        
        輸出
        0    1.0
        1    1.0
        dtype: float64
        ---------------------------------------------------------------------------
        ValueError                                Traceback (most recent call last)
        <ipython-input-30-2770688874d9> in <module>()
        
        
        ​#先轉化爲object類型,在轉化爲string
        ​
        s.astype('str').astype('string')
        
        0    1.0
        1    1.0
        dtype: string
        
        ​
        
        ​

 

  1. 拆分和拼接
    1. str.split方法
      1. s.str.split(pat=None, n=-1, expand=False) #str.split方法必須時字符串
      2. 根據某一元素分隔,默認空格,split後的類型是object,因爲Series中的元素已經不是string,而包含了list,且string類型只能含有字符串。
        s=pd.Series(['a b c',np.nan,'f_g_h'],dtype='string')
        print(s)
        print(s.str.split())
        print(s.str.split('_'))
        
        
        a b c
        1     <NA>
        2    f_g_h
        dtype: string
        0    [a, b, c]
        1         <NA>
        2      [f_g_h]
        dtype: object
        0      [a b c]
        1         <NA>
        2    [f, g, h]
        
        
        print(s.str.split('_').str[0])
        
        0    a b c
        1     <NA>
        2        f
        dtype: object

         

      3. pd.Series(['a_b_c',['a','b','c']],dtype='string')
        
        
        這樣會報錯,string類型必須是字符串或者包含NaN
      4. str方法: 可以進行元素的選擇,如果該單元格元素是列表,那麼str[i]表示取出第i個元素,如果是單個元素,則先把元素轉化爲列表在取出

        print(s)
        print(s.str.split('_').str[1])
        print(s.str[0])
        
        
        0    a_b_c
        1     <NA>
        2    c_d_e
        dtype: string
        0       b
        1    <NA>
        2       d
        dtype: object
        0       a
        1    <NA>
        2       c
        dtype: string

         

      5. s=pd.Series(['a_b_c',['a','b','c']],dtype='object')
        print(s)
        s.str[1]
        
        
        
        0        a_b_c
        1    [a, b, c]
        dtype: object
        0    _
        1    b
        dtype: object
        #expand 參數控制了是否將列拆開,n表述最多分隔多少次
        s.str.split('_',expand=True)
        
        結果:	    0	1	2
                0	a	b	c
                1	NaN	NaN	NaN
        
        
        s.str.split('_',expand=True,n=1)
        
        結果: 
                    0	1
                0	a	b_c
                1	NaN	NaN

         

    2. str.cat方法
      1. s.str.cat(others=None, sep=None, na_rep=None, join='left')
        1. 不同對象的拼接模式 cat對於不同對象的作用結果不同,其中對象包括:單列,雙列,多列
          1. 對於單個Series而言,就是所有的元素進行字符合併爲一個字符串
            s=pd.Series(['ab',None,'d'],dtype='string')
            print(s)
            
            結果
                0      ab
                1    <NA>
                2       d
                dtype: string
               
            print(s.str.cat()) 
              
            結果:
            
             abd
          2. sep分隔參數,缺失值替代字符na_sep

            s.str.cat(sep=',')
            
            結果:'ab,d'
            
            s.str.cat(sep=',',na_rep='*')
            
            結果 'ab,*,d'

             

        2. 對於兩個Series合併,是對應索引的元素進行合併

          s2=pd.Series(['24',None,None],dtype='string')
          print('s2\n',s2)
          print('cat:\n',s.str.cat())
          
          
          s2
          0      24
          1    <NA>
          2    <NA>
          dtype: string
          
          
          cat:
           abd
        3. 多列拼接剋分爲表的拼接和Series的拼接

          1. 表的拼接

            print(s)
            s3=pd.DataFrame({0:['1','3','5'],1:['5','b',None]},dtype='string')
            print(s3)
            s.str.cat(s3,na_rep='*')
            
            
            結果:
            0      ab
            1    <NA>
            2       d
            dtype: string
            
               0     1
            0  1     5
            1  3     b
            2  5  <NA>
            
            
            0    ab15
            1     *3b
            2     d5*
            dtype: string

             

          2. 多個Series的拼接

            s.str.cat([s+'0',s*2,s*3])
            
            0    abab0ababababab
            1               <NA>
            2           dd0ddddd
            dtype: string
      2. cat 的索引對齊

        1. 當前版本如果兩邊的索引不相同且未指定join參數,默認左連接,設置join=‘left

          print(s)
          s2=pd.Series(list('abc'),index=[1,2,3],dtype='string')
          print(s2)
          print(s.str.cat(s2,na_rep='*'))
          
          
          結果
          0      ab
          1    <NA>
          2       d
          dtype: string
          1    a
          2    b
          3    c
          dtype: string
          0    ab*
          1     *a
          2     db
          dtype: string

           

  2. 替換
    1. str.replace常見用法
      s=pd.Series(['A','B','C','Aaba','',np.nan,'CANB','dog','cat'],dtype='string')
      print(s)
      print(s.str.replace(r'^[AB]','**'))
      
      # ^[AB]以A或者B開頭
      
      結果:
          0       A
      1       B
      2       C
      3    Aaba
      4        
      5    <NA>
      6    CANB
      7     dog
      8     cat
      dtype: string
      0       **
      1       **
      2        C
      3    **aba
      4         
      5     <NA>
      6     CANB
      7      dog
      8      cat
      dtype: string

       

    2. 子組和函數替換
      1. 通過正整數調用子組(0返回字符本身,從1開始纔是子組)
        print(s)
        s.str.replace(r'([ABC])(\w+)',lambda x:x.group(2)[1:]+'*')
        
        結果:
        0       A
        1       B
        2      C_
        3    Aaba
        4        
        5    <NA>
        6    CANB
        7     dog
        8     cat
        dtype: string
        0       A
        1       B
        2       *
        3     ba*
        4        
        5    <NA>
        6     NB*
        7     dog
        8     cat
        dtype: string

         

      2. 利用?P<> 表達式可以對子組命名調用
        s.str.replace(r'(?P<one>[ABC])(?P<two>\w+)',lambda x:x.group('two')[1:]+'*')
        
        結果:
        0       A
        1       B
        2       *
        3     ba*
        4        
        5    <NA>
        6     NB*
        7     dog
        8     cat
        dtype: string

         

    3. 關於str.replace注意事項
      1. str.replace賦值參數不能未pd.NA,需要先轉換爲object在轉換回來
        #str.replace賦值參數不得爲pd.NA 
        # print(pd.Series(['A','B'],dtype='string').str.replace(r'[A]',pd.NA))
        
        pd.Series(['A','B'],dtype='string').astype('O').replace(r'[A]',pd.NA,regex=True).astype('string')

         

      2. 對於string類型Series在使用replace函數時不能使用正則表達式替換
        print(pd.Series(['A','B'],dtype='string').replace(r'[A]','C',regex=True))
        print(pd.Series(['A','B'],dtype='O').replace(r'[A]','C',regex=True))
        
        0    A
        1    B
        dtype: string
        0    C
        1    B
        dtype: object

         

      3. 注意事項:
        1. str.replace 針對的時object和string類型,默認時以正則表達式爲操作,目前暫時不支持DataFrame使用
        2. repalce針對的時任意類型的序列或數據框,,如果以正則表達式替換,需要設置regex=True,該方法通過字典可支持多列替換
  3. 子串匹配與提取
    1. str.extract方法
      1. 常用方法
        pd.Series(['10-87','10-88'],dtype='string').str.extract(r'([\d]{2})-([\d]{2})')
        
        結果
        	0	1
        0	10	87
        1	10	88
        
        
        pd.Series(['10-87','10-88','-89'],dtype='string').str.extract(r'(?P<name_1>[\d]{2})-(?P<name_2>[\d]{2})')
        
        結果
            name_1	name_2
        0	10	   87
        1	10	   88
        2	<NA>	<NA>
        
        
        pd.Series(['10-87','10-88','-89'],dtype='string').str.extract(r'(?P<name_1>[\d]{2})?-(?P<name_2>[\d]{2})')
        
        	name_1	name_2
        0	10	87
        1	10	88
        2	<NA>	89
        1
        ​
      2. expand方法(默認爲True)
        1. 對於一個子組的Series 如果expand設置爲False,則返回Series,若大於一個子組,則expand參數無效,全部返回DataFrame
          s = pd.Series(["a1", "b2", "c3"], ["A11", "B22", "C33"], dtype="string")
          s
          
          輸出:
          A11    a1
          B22    b2
          C33    c3
          dtype: string
          
          s.str.extract(r'([\w])')
          結果
          	0
          A11	a
          B22	b
          C33	c
          
          s.str.extract(r'([\w])',expand=False)
          
          結果
          A11    a
          B22    b
          C33    c
          dtype: string
          
          
          s.str.extract(r'([\w])([\d])')
          	0	1
          A11	a	1
          B22	b	2
          C33	c	3

           

        2. 對於一個子組的Index,如果expand設置爲False,則返回提取後的Index,若大於一個子組且expand爲False,報錯
          s.index.str.extract(r'([\w])([\d])',expand=False) #報錯
          
          
          ValueError: only one regex group is supported with Index
          

           

    2. str.extractall方法

      1. 與 extract只匹配一個符合條件的表達式不同,extractall會找出所有符合條件的字符串,並建立多級索引

        s = pd.Series(["a1a2", "b1", "c1"], index=["A", "B", "C"],dtype="string")
        # print(s)
        two_groups = '(?P<letter>[a-z])(?P<digit>[0-9])'
        s.str.extract(two_groups, expand=True)
        
        
        	letter	digit
        A	a	1
        B	b	1
        C	c	1
        
        
        
        s.str.extractall(two_groups)
        輸出
        
        		letter	digit
            match		
        A	0	a	1
        1	a	2
        B	0	b	1
        C	0	c	1

         

      2. 如果想查看第i層匹配,可使用xs方法

        s = pd.Series(["a1a2", "b1b2", "c1c2"], index=["A", "B", "C"],dtype="string")
        s.str.extractall(two_groups)
        
            letter	digit
        match		
        A	0	a	1
        1	a	2
        B	0	b	1
        1	b	2
        C	0	c	1
        1	c	2
        
        
        
        s.str.extractall(two_groups).xs(0,level='match')
        
        	letter	digit
        A	a	1
        B	b	1
        C	c	1
        
        s.str.extractall(two_groups).xs(1,level='match')
        
        
        	letter	digit
        A	a	2
        B	b	2
        C	c	2

         

    3. str.contains str.match
      1. str.contains 檢測是否包含某種正則模式

        
        pd.Series(['1', None, '3a', '3b', '03c'], dtype="string").str.contains(r'[0-9][a-z]')
        
        
        0    False
        1     <NA>
        2     True
        3     True
        4     True
        dtype: boolean
        
        
        
        #將空設置爲false
        pd.Series(['1', None, '3a', '3b', '03c'], dtype="string").str.contains('a', na=False)
        0    False
        1    False
        2     True
        3    False
        4    False
        dtype: boolean

         

      2. str.match 依賴於python的re.match,檢測內容爲是否從頭開始包含該正則模式
        pd.Series(['1', None, '3a_', '3b', '03c'], dtype="string").str.match(r'[0-9][a-z]',na=False)
        
        
        0    False
        1    False
        2     True
        3     True
        4    False
        dtype: boolean

         

  4. 常用字符串方法
    1. 過濾型方法
      1. str.strip 過濾空格
        s=pd.Series(list('abc'),index=[' space1  ','space2  ','  space3'],dtype="string")
        print(s.index)
        s.index.str.strip()
        
        Index([' space1  ', 'space2  ', '  space3'], dtype='object')
        Index(['space1', 'space2', 'space3'], dtype='object')

         

      2. str.lower str.upper
        pd.Series('A',dtype="string").str.lower()
        
        輸出
        0    a
        dtype: string
        
        
        pd.Series('a',dtype="string").str.upper()
        
        輸出:
        0    A
        dtype: string

         

      3. str.swapcase str.capitalize    :分別表示交換字母大小寫和大寫首字母
    2. isnumeric方法 檢查每一位是否都是數字
      pd.Series(['1.2','1','-0.3','a',np.nan],dtype="string").str.isnumeric()
      
      0    False
      1     True
      2    False
      3    False
      4     <NA>
      dtype: boolean

       

  5. 問題與練習
    1.  
      1. str對象方法和df/Series對象方法有什麼區別?
      2. 給出一列string類型,如何判斷單元格是否是數值型數據?
        pd.Series(['1.2','1','-0.3','a',np.nan,1]).apply(lambda x:True if type(x)in [float,int] and x==x else False)
        

         

      3.  rsplit方法的作用是什麼?它在什麼場合下適用?
        1. 從右邊開始分隔,處理的字符串比較靠近右邊的時候,容易數;
      4.  在本章的第二到第四節分別介紹了字符串類型的5類操作,請思考它們各自應用於什麼場景
        1. 拆分.str.split()比如2019年,我們只關注2019 

        2. 拼接.str.cat()  將幾列拼接成一列

        3. 替換.str.replace()將Na替換成特定的值,比如衆數

        4. 匹配.str.contains() .str.match()   查找包含特定值的

        5. 提取.str.extract() .str.extractall()  查找每個元素中特定的正則表達式的格式的內容並提取出來


          練習

          1.  現有一份關於字符串的數據集,請解決以下問題:
            (a)現對字符串編碼存儲人員信息(在編號後添加ID列),使用如下格式:“×××(名字):×國人,性別×,生於×年×月×日”
            pd.DataFrame(d.姓名+','+d.國籍+'國人,'+'性別:'+d.性別+','+'出生於'+d.出生年+'年'+d.出生月+'月'+d.出生日+'日')

            (b)將(a)中的人員生日信息部分修改爲用中文表示(如一九七四年十月二十三日),其餘返回格式不變。
            (c)將(b)中的ID列結果拆分爲原列表相應的5列,並使用equals檢驗是否一致。
          2.  現有一份半虛擬的數據集,第一列包含了新型冠狀病毒的一些新聞標題,請解決以下問題:
            (a)選出所有關於北京市和上海市新聞標題的所在行。
            d=pd.read_csv('data/String_data_two.csv').head()
            d.head()
            d[d.col1.str.contains('北京|上海')]
            
            輸出:	
                            col1	col2	col3
            4	上海開學日期延至3月	-95	    4.05

            (b)求col2的均值。
             (c)求col3的均值。
  • d.col2.astype('int').mean()
    d.columns=d.columns.str.strip()
    d.columns
    d.col3.astype('float').mean()

    應該是存在問題,怎麼可能出這麼簡單的/。。。。。。等着去看下參考答案。

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章