2020-005 pandas與numpy中的字符串處理

pandas與numpy中的字符串處理

問題解答

上次留了一個小問題,不知道大家想清楚了沒有?

其實np.apply_along_axis實現(xiàn)的也是軸上的操作,對軸上的值統(tǒng)一用函數(shù)進行處理,然后返回值。

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都是可能要發(fā)生改變的軸,指定的軸有1個值,所以送入函數(shù)的有1個值,剩下的維度就是送入的次數(shù)。

所以函數(shù)每次拿到的是長度為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時,顯然送入函數(shù)的就是一個長度為2的list,送入了一次。

那么問題就出在處理的次數(shù)上。

axis=0的時候,兩個字符串是分兩次處理的,在第一次返回['hello']的時候,因為函數(shù)只返回一個值,所以numpy從中提取'hello'并由此獲知返回的數(shù)據(jù)類型為<U5<是小端存儲的意思,U表明該字符串為unicode字符,5表明長度為5,而我們知道numpy中所有的數(shù)據(jù)類型都是一致的。所以當?shù)诙畏祷?code>['sssimon']的時候,numpy也拿到了'sssimon'并存儲了,但是由于numpy在輸出的時候是根據(jù)數(shù)據(jù)類型進行輸出的,類型為<U5,所以只輸出了5個字符。

axis=1的時候,返回的是列表['hello', 'sssimon'],numpy自動根據(jù)列表里最長的字符串進行類型推斷,為<U7,也就不會出現(xiàn)輸出時的截斷操作。 這就是造成兩者差異的原因,其實從給出的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模塊實現(xiàn)了例如endswith,startswith,len,strip等基礎(chǔ)字符串的常用函數(shù)。

當然我比較常用的就是replace,里面還可以用正則表達式。

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

out:

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

我們可以用內(nèi)置的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函數(shù)更簡單直觀一點。

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

out:

0    sssimon
1     edward
Name: name, dtype: object

pandas中字符串處理只在series中可用,而numpy沒有這個限制,因為numpy內(nèi)部存儲的全都是同一種類型。

np.char模塊也實現(xiàn)了常用的lower,strip,replace,decode,encode,add等函數(shù),其本質(zhì)上都是對單元素或者多元素調(diào)用函數(shù),函數(shù)比較少,感覺不如pandas中的字符串處理靈活性大。

最后

字符串處理在數(shù)據(jù)分析中常用于數(shù)據(jù)清洗過程,例如在分析轉(zhuǎn)專業(yè)數(shù)據(jù)時,我拿到的pdf識別后的excel并沒有那么整潔,會出現(xiàn)下面這種情況。

image-20200727174324127

這種情況看似比較棘手,但是用正則就很容易。

data.loc['當前學院'] = data['當前學院'].str.replace('學$','學院')

你,學會了嗎?

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容