Joyful Pandas 第六章学习笔记

这次学习使用JupyterLab开展,详细内容不再详细展开,仅附上部分在我的知识结构里重要的部分。

内容主体框架:

在这里插入图片描述

拆分和拼接

1.str.split方法

(a)分割符与str的位置元素选取
s = pd.Series(['a_b_c', 'c_d_e', np.nan, 'f_g_h'], dtype='string')

s.str.split('_')
(b)expand参数控制是否将列拆开。n参数代表最多分割多少次
s.str.split('_', expand=True, n=1)

2.str.cat方法

(a) 不同对象的拼接模式
a.1 对单个Series而言,指所有元素的字符合并为一个字符串
s = pd.Series(['ab', None, 'd'], dtype='string')

s.str.cat()
a.2 对于两个Series合并而言,是对应索引的元素进行合并
s2 = pd.Series(['24', None, None], dtype='string')

s.str.cat(s2)
a.3 多列拼接可以分为表的拼接和多Series拼接
(b) cat中的索引对齐

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

替换

1.str.replace

2.关于str.replace的注意事项

(a)str.replace赋值参数不得为pd.NA
pd.Series(['A', 'B'], dtype='string').astype('O').replace(r'[A]', pd.NA, regex=True).astype('string')
(b)对于string类型Series,在使用replace函数时不能使用正则表达式替换
pd.Series(['A', 'B'], dtype='string').replace(r'[A]', 'C', regex=True)
©string类型序列如果存在缺失值,不能使用replace替换
pd.Series(['A', np.nan], dtype='string').str.replace('A', 'B')

子串匹配与提取

1.str.extract方法

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

2.str.extractall方法

pd.Series(['10-87', '10-88', '10-s = pd.Series(["a1a2", "b1", "c1"], index=["A", "B", "C"], dtype="string")
two_groups = '(?P<letter>[a-z])(?P<digit>[0-9])'
s.str.extract(two_groups, expand=True)

3.str.contains和str.match

pd.Series(['10-87', '10-88', '10-pd.Series(['1', None, "3a", "3b", "03c"], dtype="string").str.contains(r'[0-9][a-z]')

常用字符串方法

1.过滤型方法

(a)str.strip 用于过滤空格
pd.Series(list('abc'), index=[' space1 ', 'space2 ', ' space3'], dtype="string").index.str.strip()
(b)str.lower和str.upper
pd.Series('A', dtype="string").str.lower()
pd.Series('A', pd.Series('a', dtype="string").str.upper()
(c)str.swapcase和str.capitalize分别表示交换字母大小和大写首字母
pd.Series('abCD', dtype="string").str.swapcase()
pd.Series('abCD', dtype="string").str.capitalize()

2.isnumeric方法

pd.Series(['1.2', '1', '-0.3', 'a', np.nan], dtype="string").str.isnumeric()

问题与练习

1.问题

【问题一】str对象方法和df/Series对象方法有什么区别?

答:主要区别有以下两点:
1.str.replace针对的是object类型或string类型,默认以正则表达式操作,目前暂时不支持DataFrame/Series;
2.str.replace针对的是任意类型的序列或数据框,如以正则表达式替换,需要设置regex=True,该方法通过字典可支持多列替换。

【问题二】给出一列string类型,如何判断单元格是否为数值型数据?

答:可用正则表达式匹配:str.contains(r’-?([0-9]\d*)(.\d+)?$’)

问题三】rsplit方法的作用是什么?它在什么场合下适用?

答:rsplit方法通过指定分隔符对字符串进行分割并返回一个列表,默认分隔符为所有空字符,包括空格、换行(\n)、制表符(\t)等。类似于 split() 方法,只不过是从字符串最后面开始分割。

2.练习

【练习一】 现有一份关于字符串的数据集,请解决以下问题:

(a)现对字符串编码存储人员信息(在编号后添加ID列),使用如下格式:“×××(名字):×国人,性别×,生于×年×月×日”

df = pd.read_csv('String_data_one.csv',index_col='人员编号').astype('str')
df.head()

(df['姓名']+':'+df['国籍']+'国人,性别'
          +df['性别']+',生于'
          +df['出生年']+'年'
          +df['出生月']+'月'+df['出生日']+'日').to_frame().rename(columns={0:'ID'})

在这里插入图片描述
在这里插入图片描述

(b)将(a)中的人员生日信息部分修改为用中文表示(如一九七四年十月二十三日),其余返回格式不变。

L_year = list('零一二三四五六七八九')
L_one = [s.strip() for s in list('  二三四五六七八九')]
L_two = [s.strip() for s in list(' 一二三四五六七八九')]
df_new = (df['姓名']+':'+df['国籍']+'国人,性别'+df['性别']+',生于'
          +df['出生年'].str.replace(r'\d',lambda x:L_year[int(x.group(0))])+'年'
          +df['出生月'].apply(lambda x:x if len(x)==2 else '0'+x)\
                      .str.replace(r'(?P<one>[\d])(?P<two>\d?)',lambda x:L_one[int(x.group('one'))]
                      +bool(int(x.group('one')))*'十'+L_two[int(x.group('two'))])+'月'
          +df['出生日'].apply(lambda x:x if len(x)==2 else '0'+x)\
                      .str.replace(r'(?P<one>[\d])(?P<two>\d?)',lambda x:L_one[int(x.group('one'))]
                      +bool(int(x.group('one')))*'十'+L_two[int(x.group('two'))])+'日')\
          .to_frame().rename(columns={0:'ID'})
df_new.head()

在这里插入图片描述

(c)将(b)中的ID列结果拆分为原列表相应的5列,并使用equals检验是否一致。

dic_year = {i[0]:i[1] for i in zip(list('零一二三四五六七八九'),list('0123456789'))}
dic_two = {i[0]:i[1] for i in zip(list('十一二三四五六七八九'),list('0123456789'))}
dic_one = {'十':'1','二十':'2','三十':'3',None:''}
df_res = df_new['ID'].str.extract(r'(?P<姓名>[a-zA-Z]+):(?P<国籍>[\d])国人,性别(?P<性别>[\w]),生于(?P<出生年>[\w]{4})年(?P<出生月>[\w]+)月(?P<出生日>[\w]+)日')
df_res['出生年'] = df_res['出生年'].str.replace(r'(\w)+',lambda x:''.join([dic_year[x.group(0)[i]] for i in range(4)]))
df_res['出生月'] = df_res['出生月'].str.replace(r'(?P<one>\w?十)?(?P<two>[\w])',lambda x:dic_one[x.group('one')]+dic_two[x.group('two')]).str.replace(r'0','10')
df_res['出生日'] = df_res['出生日'].str.replace(r'(?P<one>\w?十)?(?P<two>[\w])',lambda x:dic_one[x.group('one')]+dic_two[x.group('two')]).str.replace(r'^0','10')
df_res.head()

df_res.equals(df)

在这里插入图片描述

【练习二】现有一份半虚拟的数据集,第一列包含了新型冠状病毒的一些新闻标题,请解决以下问题:

(a)选出所有关于北京市和上海市新闻标题的所在行。

df = pd.read_csv('String_data_two.csv')
df.head()

df[df['col1'].str.contains(r'[北京]{2}|[上海]{2}')].head()

在这里插入图片描述
在这里插入图片描述
(b)求col2的均值。

df['col2'][~(df['col2'].str.replace(r'-?\d+','True')=='True')]
df.loc[[309,396,485],'col2'] = [0,9,7]
df['col2'].astype('int').mean()

(c)求col3的均值。

df.columns
df.columns = df.columns.str.strip()
df.columns
df['col3'].head()
df['col3'][~(df['col3'].str.replace(r'-?\d+\.?\d+','True')=='True')]
df.loc[[28,122,332],'col3'] = [355.3567,9056.2253, 3534.6554]
df['col3'].astype('float').mean()
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值