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的一个list
,print
一下也可以看出来。
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('学$','学院')
你,学会了吗?
网友评论