- string 类型的性值
- string 与object区别
- 字符存取方法,string返回相应数据的Nullable类型,object会因缺失值存在而改变返回类型;
- 某些Series方法不能再string上使用,Series.str.decode() 因为存储的是字符串而不是字节
- string类型在缺失值存储或运算时,类型广播时pd.NAN,而不是np.nan
- string类型的转化
- 将其他类型的数据直接转化为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
- 将其他类型的数据直接转化为string可能会出错,办法如下
- string 与object区别
- 拆分和拼接
- str.split方法
-
s.str.split(pat=None, n=-1, expand=False) #str.split方法必须时字符串
- 根据某一元素分隔,默认空格,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
-
pd.Series(['a_b_c',['a','b','c']],dtype='string') 这样会报错,string类型必须是字符串或者包含NaN
-
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
-
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
-
- str.cat方法
- s.str.cat(others=None, sep=None, na_rep=None, join='left')
- 不同对象的拼接模式 cat对于不同对象的作用结果不同,其中对象包括:单列,双列,多列
- 对于单个Series而言,就是所有的元素进行字符合并为一个字符串
s=pd.Series(['ab',None,'d'],dtype='string') print(s) 结果 0 ab 1 <NA> 2 d dtype: string print(s.str.cat()) 结果: abd
-
sep分隔参数,缺失值替代字符na_sep
s.str.cat(sep=',') 结果:'ab,d' s.str.cat(sep=',',na_rep='*') 结果 'ab,*,d'
- 对于单个Series而言,就是所有的元素进行字符合并为一个字符串
-
对于两个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
-
多列拼接剋分为表的拼接和Series的拼接
-
表的拼接
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
-
多个Series的拼接
s.str.cat([s+'0',s*2,s*3]) 0 abab0ababababab 1 <NA> 2 dd0ddddd dtype: string
-
- 不同对象的拼接模式 cat对于不同对象的作用结果不同,其中对象包括:单列,双列,多列
-
cat 的索引对齐
-
当前版本如果两边的索引不相同且未指定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
-
- s.str.cat(others=None, sep=None, na_rep=None, join='left')
- str.split方法
- 替换
- 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
- 子组和函数替换
- 通过正整数调用子组(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
- 利用?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
- 通过正整数调用子组(0返回字符本身,从1开始才是子组)
- 关于str.replace注意事项
- 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')
- 对于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
- 注意事项:
- str.replace 针对的时object和string类型,默认时以正则表达式为操作,目前暂时不支持DataFrame使用
- repalce针对的时任意类型的序列或数据框,,如果以正则表达式替换,需要设置regex=True,该方法通过字典可支持多列替换
- str.replace赋值参数不能未pd.NA,需要先转换为object在转换回来
- str.replace常见用法
- 子串匹配与提取
- str.extract方法
- 常用方法
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
- expand方法(默认为True)
- 对于一个子组的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
- 对于一个子组的Index,如果expand设置为False,则返回提取后的Index,若大于一个子组且expand为False,报错
s.index.str.extract(r'([\w])([\d])',expand=False) #报错 ValueError: only one regex group is supported with Index
- 对于一个子组的Series 如果expand设置为False,则返回Series,若大于一个子组,则expand参数无效,全部返回DataFrame
- 常用方法
-
str.extractall方法
-
与 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
-
如果想查看第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
-
- str.contains str.match
-
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
- 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
-
- str.extract方法
- 常用字符串方法
- 过滤型方法
- 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')
- 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
- str.swapcase str.capitalize :分别表示交换字母大小写和大写首字母
- str.strip 过滤空格
- 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
- 过滤型方法
- 问题与练习
-
- str对象方法和df/Series对象方法有什么区别?
- 给出一列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)
- rsplit方法的作用是什么?它在什么场合下适用?
- 从右边开始分隔,处理的字符串比较靠近右边的时候,容易数;
- 在本章的第二到第四节分别介绍了字符串类型的5类操作,请思考它们各自应用于什么场景
-
拆分.str.split()比如2019年,我们只关注2019
-
拼接.str.cat() 将几列拼接成一列
-
替换.str.replace()将Na替换成特定的值,比如众数
-
匹配.str.contains() .str.match() 查找包含特定值的
-
提取.str.extract() .str.extractall() 查找每个元素中特定的正则表达式的格式的内容并提取出来
练习- 现有一份关于字符串的数据集,请解决以下问题:
(a)现对字符串编码存储人员信息(在编号后添加ID列),使用如下格式:“×××(名字):×国人,性别×,生于×年×月×日”pd.DataFrame(d.姓名+','+d.国籍+'国人,'+'性别:'+d.性别+','+'出生于'+d.出生年+'年'+d.出生月+'月'+d.出生日+'日')
(b)将(a)中的人员生日信息部分修改为用中文表示(如一九七四年十月二十三日),其余返回格式不变。
(c)将(b)中的ID列结果拆分为原列表相应的5列,并使用equals检验是否一致。 - 现有一份半虚拟的数据集,第一列包含了新型冠状病毒的一些新闻标题,请解决以下问题:
(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()
应该是存在问题,怎么可能出这么简单的/。。。。。。等着去看下参考答案。