2020-005 pandas与numpy中的字符串处理

2022-01-13  本文已影响0人  SSSimonYang

pandas与numpy中的字符串处理

问题解答

上次留了一个小问题,不知道大家想清楚了没有?

其实np.apply_along_axis实现的也是轴上的操作,对轴上的值统一用函数进行处理,然后返回值。

import numpy as np
array = np.array([['hello world','sssimon yang']]) 
np.apply_along_axis(lambda a:[i.split(' ')[0] for i in a],axis=0,arr=array)

out:

array([['hello', 'sssim']], dtype='<U5')

在这一步中,处理的是第一个轴,第一个轴有1个值,剩下的还有一个轴,维度为2,所以处理了两次。

应该记住,每次指定的axis都是可能要发生改变的轴,指定的轴有1个值,所以送入函数的有1个值,剩下的维度就是送入的次数。

所以函数每次拿到的是长度为1的一个listprint一下也可以看出来。

np.apply_along_axis(lambda a:print(a),axis=0,arr=array)
['hello world']
['sssimon yang']

out:

array([None, None], dtype=object)

用下面的例子会看的更容易些。

data = np.arange(0, 24).reshape((2,3,4))
np.apply_along_axis(lambda a:print(a),axis=1,arr=data)

[0 4 8]
[1 5 9]
[ 2  6 10]
[ 3  7 11]
[12 16 20]
[13 17 21]
[14 18 22]
[15 19 23]

out:

array([[None, None, None, None],
       [None, None, None, None]], dtype=object)

处理的是第二个轴,每次送入三个值,剩下的维度为2X4,所以送入8次,这8次的每三个值都是依次遍历第一层1,2和最后一层1,2,3,4提取组成的。最后再组成一个2X4的ndarray。

data = np.arange(0, 24).reshape((2,3,4))
np.apply_along_axis(lambda a:np.mean(a),axis=1,arr=data) 

out:

array([[ 4.,  5.,  6.,  7.],
       [16., 17., 18., 19.]])

回到之前。

np.apply_along_axis(lambda a:[i.split(' ')[0] for i in a],axis=1,arr=array)

out:

array([['hello', 'sssimon']], dtype='<U7')

axis=1时,显然送入函数的就是一个长度为2的list,送入了一次。

那么问题就出在处理的次数上。

axis=0的时候,两个字符串是分两次处理的,在第一次返回['hello']的时候,因为函数只返回一个值,所以numpy从中提取'hello'并由此获知返回的数据类型为<U5<是小端存储的意思,U表明该字符串为unicode字符,5表明长度为5,而我们知道numpy中所有的数据类型都是一致的。所以当第二次返回['sssimon']的时候,numpy也拿到了'sssimon'并存储了,但是由于numpy在输出的时候是根据数据类型进行输出的,类型为<U5,所以只输出了5个字符。

axis=1的时候,返回的是列表['hello', 'sssimon'],numpy自动根据列表里最长的字符串进行类型推断,为<U7,也就不会出现输出时的截断操作。 这就是造成两者差异的原因,其实从给出的dtype中也可以看出来一些线索。

字符串处理

pandas和numpy中都有字符串处理的模块,pandas在pd.Series.str模块里,而numpy在np.char模块里。

data = pd.DataFrame({'name':['sssimon yang','edward wang'],'age':[18,22]})

pd.Series.str是直接可以用切片操作的。

data.name.str[-4:]

out:

0    yang
1    wang
Name: name, dtype: object

str模块实现了例如endswith,startswith,len,strip等基础字符串的常用函数。

当然我比较常用的就是replace,里面还可以用正则表达式。

data.name.str.replace('.ang','zhang')

out:

0    sssimon zhang
1     edward zhang
Name: name, dtype: object

我们可以用内置的split完成类似之前的拆分。

data.name.str.split()

out:

0    [sssimon, yang]
1     [edward, yang]
Name: name, dtype: object

拆分后返回的是list,dtype为object,我们可以借用str的切片操作来提取一下第一个值。

data.name.str.split().str[0]

out:

0    sssimon
1     edward
Name: name, dtype: object

成功了!

当然其实用apply函数更简单直观一点。

data.name.apply(lambda x:x.split()[0])

out:

0    sssimon
1     edward
Name: name, dtype: object

pandas中字符串处理只在series中可用,而numpy没有这个限制,因为numpy内部存储的全都是同一种类型。

np.char模块也实现了常用的lower,strip,replace,decode,encode,add等函数,其本质上都是对单元素或者多元素调用函数,函数比较少,感觉不如pandas中的字符串处理灵活性大。

最后

字符串处理在数据分析中常用于数据清洗过程,例如在分析转专业数据时,我拿到的pdf识别后的excel并没有那么整洁,会出现下面这种情况。

image-20200727174324127

这种情况看似比较棘手,但是用正则就很容易。

data.loc['当前学院'] = data['当前学院'].str.replace('学$','学院')

你,学会了吗?

上一篇 下一篇

猜你喜欢

热点阅读