Pandas数据处理之文本数据处理

Pandas 文本数据处理

  • 一、string类型的性质
    • string与object的区别
    • string类型的转换
  • 二、拆分与拼接
    • str.splite方法
      • a)分割符与str的位置元素选取
      • b)expand参数控制了是否拆开成列
      • c)n参数代表最多分割多少次
      • d)expand参数与n参数组合
    • str.cat方法
      • a) 不同对象的拼接模式
        • 1) 对于单个Series而言
        • 2) 对于两个Series合并而言
      • b) cat的索引对齐
  • 三、替换
    • 正则表达式
    • str.replace的常见用法
    • 子组与函数替换
    • 关于str.replace的注意事项
      • 明确str.replace和replace是不同的
        • a) str.replace赋值参数不得为pd.NA
        • b) replace针对的是任意类型的序列或数据框
        • c) string类型和object类型序列如果存在缺失值,都不能使用str.replace替换,只能用replace.
  • 四、子串匹配与提取
    • str.extract方法
      • a) 常见用法
        • 1) 使用子组名作为列名
        • 2) 利用'?'正则标记选择部分提取
      • b) expand参数(默认为True)
    • str.extractall方法
      • a) 与extract只匹配第一个符合条件的表达式不同,extractall会找出所有符合条件的字符串,并建立多级索引(即使只找到一个)
      • b) 如果想查看第i层匹配,可使用xs方法
    • str.contains方法
    • str.match方法
  • 五、常用字符串方法
    • 过滤型方法
      • str.strip
      • str.lower
      • str.upper
      • str.swapcase
      • str.capitalize
    • isnumeric方法

一、string类型的性质

string与object的区别

1.字符存取方法会返回相应数据的Nullable类型(即Int,String,Float等),这一类型数据不会随缺失值的存在而改变类型;而object会随缺失值的存在而改变返回其他类(整型列转为浮点;而字符由于无法转化为浮点,因此只能归并为object类型)
2.某些Series方法不能在string上使用,例如: Series.str.decode(),因为存储的是字符串而不是字节
3.string类型在缺失值存储或运算时,类型会广播为pd.NA,而不是浮点型np.nan

string类型的转换

如果将一个其他类型的容器直接转换string类型可能会出错:
pd.Series([1,'1.']).astype('string') #报错
pd.Series([1,2]).astype('string') #报错
pd.Series([True,False]).astype('string') #报错

当下正确的方法是分两部转换,先转为str型object,在转为string类型:

pd.Series([True,False]).astype('str').astype('string')
#output:
0    1
1    1.
dtype: string

pd.Series([1,2]).astype('str').astype('string')
#output:
0    1
1    2
dtype: string

pd.Series([True,False]).astype('str').astype('string')
#output:
0    True
1    False
dtype: string

二、拆分与拼接

str.splite方法

a)分割符与str的位置元素选取

#原数据:
0    a_b_c
1    c_d_e
2     <NA>
3    f_g_h
dtype: string

根据某一个元素分割,默认为空格

s.str.split('_')
#output:
0    [a, b, c]
1    [c, d, e]
2         <NA>
3    [f, g, h]
dtype: object

这里需要注意split后的类型是object,因为现在Series中的元素已经不是string,而包含了list,且string类型只能含有字符串。

此方法下可以进行元素的提取:
如果该单元格元素是列表,那么str[i]表示取出第i个元素;
如果是单个元素,则先把元素转为列表再取出。

s.str.split('_').str[1]
# output:
0       b
1       d
2    <NA>
3       g
dtype: object

pd.Series(['a_b_c', ['a','b','c']], dtype="object").str[1]
#第一个元素先转为['a','_','b','_','c']
0    _
1    b
dtype: object

b)expand参数控制了是否拆开成列

s.str.split('_',expand=True)
#output:
       0          1         2
0      a          b         c
1      c          d         e
2     <NA>      <NA>      <NA>
3      f          g         h

c)n参数代表最多分割多少次

s.str.split('_',n=1)
#output:
0    [a, b_c]
1    [c, d_e]
2        <NA>
3    [f, g_h]
dtype: object

d)expand参数与n参数组合

s.str.split('_',expand=True,n=1)
#output:
      0        1
0     a       b_c
1     c       d_e
2    <NA>    <NA>
3     f       g_h

str.cat方法

a) 不同对象的拼接模式

cat方法对于不同对象的作用结果并不相同,其中的对象包括:单列、双列、多列

1) 对于单个Series而言

是指所有的元素进行字符合并为一个字符串

# 生成Series:
s = pd.Series(['ab',None,'d'],dtype='string')
#output:
0      ab
1    <NA>
2       d
dtype: string

#合并:
s.str.cat()
#output:
‘abd'

sep分隔符参数

s.str.cat(sep=',')
#output:
'ab,d'

缺失值替代字符na_rep参数

s.str.cat(sep=',',na_rep='*')
#output:
'ab,*,d'

2) 对于两个Series合并而言

是对应索引的元素进行合并

# 生成第一个Series:
s = pd.Series(['ab',None,'d'],dtype='string')
#output:
0      ab
1    <NA>
2       d
dtype: string

# 生成第二个Series:
s2 = pd.Series(['24',None,None],dtype='string')
#output:
0      24
1     <NA>
2     <NA>
dtype: string

# 合并:
s.str.cat(s2)
#output:
0    ab24
1    <NA>
2    <NA>
dtype: string

注意:缺失值pd.NA与任何值合并都为pd.NA本身

相应的sep参数与na_rep参数的应用:
合并后的两个缺失值会被同时替换成参数指定的相应字符

s.str.cat(s2,sep=',',na_rep='*')
#output:
0     ab,24
1      *,*
2      d,*
dtype: string

③ 多列拼接可以分为表的拼接和多Series拼接
表的拼接

s = pd.Series(['ab',None,'d'],dtype='string')
#output:
0      ab
1    <NA>
2       d
dtype: string

df = pd.DataFrame({0:['1','3','5'],1:['5','b',None]},dtype='string')
# output:   
   0     1
0  1     5
1  3     b
2  5   <NA>

s.str.cat(df,na_rep='*'# output: 
0    ab15
1     *3b
2     d5*
dtype: string

多个Series拼接

s = pd.Series(['ab',None,'d'],dtype='string')
#output:
0      ab
1    <NA>
2       d
dtype: string

s+'0'
#output:
0     ab0
1    <NA>
2      d0
dtype: string

s*2
#output:
0    abab
1    <NA>
2      dd
dtype: string

# 拼接:
s.str.cat([s+'0',s*2])
#output:
0    abab0abab
1         <NA>
2        dd0dd
dtype: string

b) cat的索引对齐

如果两边合并的索引不相同且未指定join参数,默认为左连接,设置join=‘left’

s = pd.Series(['ab',None,'d'],dtype='string')
#output:
0      ab
1    <NA>
2       d
dtype: string

s2 = pd.Series(list('abc'),index=[1,2,3],dtype='string')
#output:
1    a
2    b
3    c
dtype: string

# 合并:
s.str.cat(s2,na_rep='*')
#output:
0    ab*
1     *a
2     db
dtype: string

#因为是默认左链接,所以合并后的结果的index和s的index相同,s2中‘3’被忽略。

三、替换

正则表达式

  1. r前缀,不用考虑转义的问题:
    比如我们匹配信息item\n 时,如果没有r,我们要将正则表达式写成re.compile(‘item\n’);但是,当我们加上了r时,我们的正则表达式写成re.compile(r’item\n’)就可以了。

  2. ^表示行的开头

  3. $表示行的结尾

  4. 小括号()的意思是将某一部分分开成n个子组
    同时可以利用?P<…>表达式对子组命名调用,尖括号里面填子组的名字。

  5. [./-+]
    在[]内均表示字符本身;
    在[]外特殊字符,表示匹配特殊字符本身,必须要加反斜杠;
    或者用r方法

  6. \w表示[0-9a-zA-Z_]

  7. []+,‘+’号在[]外表示{1,},即1次或多次

  8. ‘?’ 匹配前面的子表达式零次或一次。
    例如,“do(es)?”可以匹配“does”中的“do”和“does”。?等价于{0,1}。

  9. 正则表达式[\w]+,\w+,[\w+] 三者的区别
    [\w]+和\w+没有区别,都是匹配多个数字、字母以及下划线;
    [\w+]表示匹配一个数字、字母、下划线或加号本身字符;

  10. [ ]表示数组而非排列,即不按固定次序位置排列,在[ ]内的字符可以任意次序出现。
    例如:
    [ABC]+
    可以匹配"AAABBBCCC,BBBAAACCC,BACCBACAACBAC,…",不是一定按固定A…B…C…的次序排列。

str.replace的常见用法

s = pd.Series(['A', 'B', 'C', 'Aaba', 'Baca','', np.nan, 'ABBA', 'dog', 'cat'],dtype="string")
#output:
0       A
1       B
2       C
3    Aaba
4    Baca
5        
6    <NA>
7    ABBA
8     dog
9     cat
dtype: string

第一个值写r开头的正则表达式,后一个写替换的字符串

s.str.replace(r'^[AB]','***')
#output:
0       ***
1       ***
2         C
3    ***aba
4    ***aca
5          
6      <NA>
7    ***BBA
8       dog
9       cat
dtype: string

s.str.replace(r'^[AB]+','***')
#output:
0       ***
1       ***
2         C
3    ***aba
4    ***aca
5          
6      <NA>
7       ***
8       dog
9       cat
dtype: string

写以$结尾的正则表达式,后一个写替换的字符串

s.str.replace(r'[AB]$','***')
#output:
0       ***
1       ***
2         C
3      Aaba
4      Baca
5          
6      <NA>
7    ABB***
8       dog
9       cat
dtype: string

子组与函数替换

通过正整数调用子组(0返回字符本身,从1开始才是子组)

s.str.replace(r'([ABC])(\w+)',lambda x:x.group(2)[1:]+'*')
#output:
0       A
1       B
2       C
3     ba*
4     ca*
5        
6    <NA>
7     BA*
8     dog
9     cat
dtype: string

利用?P<…>表达式可以对子组命名调用

s.str.replace(r'(?P[ABC])(?P\w+)',lambda x:x.group('two')[1:]+'*')
#output:
0       A
1       B
2       C
3     ba*
4     ca*
5        
6    <NA>
7     BA*
8     dog
9     cat
dtype: string

关于str.replace的注意事项

明确str.replace和replace是不同的

str.replace针对的是object类型或string类型,默认是以正则表达式为操作,目前暂时不支持DataFrame上使用

a) str.replace赋值参数不得为pd.NA

(当前版本不支持)

pd.Series(['A','B'],dtype='string').str.replace(r'[A]',pd.NA)
#报错
pd.Series(['A','B'],dtype='O').str.replace(r'[A]',pd.NA) 
#报错

解决办法:此时,可以先转为object类型再转换回来

pd.Series(['A','B'],dtype='string').astype('O').replace(r'[A]',pd.NA,regex=True).astype('string')
#output:
0    <NA>
1       B
dtype: string

b) replace针对的是任意类型的序列或数据框

如果要以正则表达式替换,需要设置regex=True,该方法通过字典可支持多列替换

  1. 对于string类型Series,在使用replace函数时不能使用正则表达式替换
pd.Series(['A','B'],dtype='string').replace(r'[A]',pd.NA,regex=True)
#output:
0    A
1    B
dtype: string
  1. 对于object类型的Series,则可以使用replace方法,并运用regex参数,使用正则表达式进行替换,所以针对str.replace不能用pd.NA作为赋值参数的问题,可以先转为object类型处理完后在转换回string类型
pd.Series(['AA','B'],dtype='O').replace(r'[A]',pd.NA,regex=True)
#output:
0    <NA>
1       B
dtype: object

c) string类型和object类型序列如果存在缺失值,都不能使用str.replace替换,只能用replace.

pd.Series(['A',np.nan],dtype='object').str.replace(np.nan,'B') 
#报错
pd.Series(['A',pd.NA],dtype='string').str.replace(pd.NA,'B') 
#报错
pd.Series(['A',np.nan],dtype='object').replace(np.nan,'B') 
#output:
0    A
1    B
dtype: object

pd.Series(['A',pd.NA],dtype='string').replace(pd.NA,'B')
#output:
0    A
1    B
dtype: string

综上,概况的说,除非需要赋值元素为缺失值(转为object再转回来),或者被赋值元素为缺失值,否则请使用str.replace方法。

四、子串匹配与提取

str.extract方法

a) 常见用法

pd.Series(['10-87', '10-88', '10-89'],dtype="string").str.extract(r'([\d]{2})-([\d]{2})')
#output:
    0   1
0  10  87
1  10  88
2  10  89

1) 使用子组名作为列名

pd.Series(['10-87', '10-88', '-89'],dtype="string").str.extract(r'(?P[\d]{2})-(?P[\d]{2})')
#output:
   name_1     name_2
0    10         87
1    10         88
2   <NA>       <NA>

2) 利用’?'正则标记选择部分提取

pd.Series(['10-87', '10-88', '-89'],dtype="string").str.extract(r'(?P[\d]{2})?-(?P[\d]{2})')
#output:
   name_1  name_2
0     10      87
1     10      88
2   <NA>      89

pd.Series(['10-87', '10-88', '10-'],dtype="string").str.extract(r'(?P[\d]{2})-(?P[\d]{2})?')
	name_1    name_2
0      10        87
1      10        88
2      10      <NA>

b) expand参数(默认为True)

s = pd.Series(["a1", "b2", "c3"], ["A11", "B22", "C33"], dtype="string")
s.index
#output:
Index(['A11', 'B22', 'C33'], dtype='object')
  1. 对于一个子组的Series,如果expand设置为False,则返回Series,若大于一个子组,则expand参数无效,全部返回DataFrame

单一子组,expand参数为True的情况:

s.str.extract(r'([\w])')
#expand参数有效,返回DataFrame: 
       0
A11    a
B22    b
C33    c

单一子组,expand参数设置为False的情况:

s.str.extract(r'([\w])',expand=False)
#expand参数有效,返回Series:
A11    a
B22    b
C33    c
dtype: string

多子组,expand参数设置为False的情况:

s.str.extract(r'([\w])([\d])',expand=False)
#expand参数无效,返回DataFrame:         
       0  1
A11    a  1
B22    b  2
C33    c  3
  1. 对于一个子组的Index,如果expand设置为False,则返回提取后的Index,若大于一个子组且expand为False,报错

单一子组,expand参数为True的情况:

s.index.str.extract(r'([\w])')
#expand参数有效,返回DataFrame:
   0
0  A
1  B
2  C

单一子组,expand参数为False的情况:

s.index.str.extract(r'([\w])',expand=False)
#expand参数有效,返回提取后的的index:
Index(['A', 'B', 'C'], dtype='object')

多子组,expand参数为True的情况:

s.index.str.extract(r'([\w])([\d])')
#expand参数有效,返回DataFrame:
    0  1
0   A  1
1   B  2
2   C  3   

多子组,expand参数为False的情况:

s.index.str.extract(r'([\w])([\d])',expand=False) 
#报错

str.extractall方法

s = pd.Series(["a1a2", "b1", "c1"], index=["A", "B", "C"],dtype="string")

two_groups = '(?P[a-z])(?P[0-9])'

s.str.extract(two_groups, expand=True)
#output:
	 letter digit
A      a       1
B      b       1
C      c       1

a) 与extract只匹配第一个符合条件的表达式不同,extractall会找出所有符合条件的字符串,并建立多级索引(即使只找到一个)

s.str.extractall(two_groups)
#output:
		  letter digit
   match             
A    0      a       1
     1      a       2
B    0      b       1
C    0      c       1
s['A']='a11'
s.str.extractall(two_groups)
#output:
			letter  digit
    match             
A     0         a      1
B     0         b      1
C     0         c      1

b) 如果想查看第i层匹配,可使用xs方法

s = pd.Series(["a1a2", "b1b2", "c1c2"], index=["A", "B", "C"],dtype="string")

s.str.extractall(two_groups).xs(1,level='match')
#output:
	letter digit
A      a     2
B      b     2
C      c     2
	

str.contains方法

作用为检测是否包含某种正则模式

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

a) 可选参数为na
当na=True时,缺失值为True,当na=False时,则相反。不放入na参数,缺失值显示其本身。

pd.Series(['1', None, '3a', '3b', '03c'], dtype="string").str.contains('a',na=False)
#output:
0    False
1    False
2     True
3    False
4    False
dtype: boolean

str.match方法

检测内容为是否从头开始包含该正则模式

pd.Series(['1', None, '3a_', '3b', '03c'], dtype="string").str.match(r'[0-9][a-z]',na=False)
#output:
0    False
1    False
2     True
3     True
4    False
dtype: boolean

pd.Series(['1', None, '_3a', '3b', '03c'], dtype="string").str.match(r'[0-9][a-z]',na=False)
#output
0    False
1    False
2    False
3     True
4    False
dtype: boolean

五、常用字符串方法

过滤型方法

str.strip

常用于过滤空格

pd.Series(list('abc'),index=[' space1  ','space2  ','  space3'],dtype="string").index.str.strip()
#output:
Index(['space1', 'space2', 'space3'], dtype='object')

str.lower

pd.Series('A',dtype="string").str.lower()
#output:
0    a
dtype: string

str.upper

pd.Series('a',dtype="string").str.upper()
#output:
0    A
dtype: string

str.swapcase

表示交换字母大小写

pd.Series('abCD',dtype="string").str.swapcase()
#output:
0    ABcd
dtype: string

str.capitalize

大写首字母

pd.Series('abCD',dtype="string").str.capitalize()
#output:
0    Abcd
dtype: string

isnumeric方法

检查每一位是否都是数字

pd.Series(['1.2','1','-0.3','a',np.nan],dtype="string").str.isnumeric()
#output:
0    False
1     True
2    False
3    False
4     <NA>
dtype: boolean

你可能感兴趣的:(Pandas数据处理之文本数据处理)