pandas數據類型(二)與numpy的str和object類型之間的區別


現象:

Numpy區分了str和object類型,其中dtype(‘S’)和dtype(‘O’)分別對應於str和object.

然而,pandas缺乏這種區別 str和object類型都對應dtype(‘O’)類型,即使強制類型為dtype(‘S’)也無濟於事

>>> import pandas as pd
>>> import numpy as np
>>>
>>>
>>> np.dtype(str)
dtype('S')
>>> np.dtype(object)
>>>
>>>
dtype('O')
>>> df = pd.DataFrame({'a': np.arange(5)})
>>> df
   a
0  0
1  1
2  2
3  3
4  4
>>> df.a.dtype
dtype('int64')
>>> df.a.astype(str).dtype
dtype('O')
>>> df.a.astype(object).dtype
dtype('O')
>>> df.a.astype(str).dtype
dtype('O')

原理:

先說結論:

Numpy的字符串dtypes不是python字符串.pandas使用python字符串,.

 

numpy與pandas的字符串不同的含義:

>>> x = np.array(['Testing', 'a', 'string'], dtype='|S7')
>>> x
array([b'Testing', b'a', b'string'], dtype='|S7')
>>>
>>>
>>> y = np.array(['Testing', 'a', 'string'], dtype=object)
>>> y
array(['Testing', 'a', 'string'], dtype=object)

現在,一個是numpy字符串dtype(固定寬度,類似c的字符串),另一個原生python字符串數組.

如果我們試圖超過7個字符,我們會看到立即的差異.numpy字符串dtype版本將被截斷,而numpy對象dtype版本可以是任意長度

>>> x[1] = 'a really really really long'
>>> x
array([b'Testing', b'a reall', b'string'], dtype='|S7')
>>>
>>> y[1] = 'a really really really long'
>>> y
array(['Testing', 'a really really really long', 'string'], dtype=object)

盡管存在unicode固定長度字符串dtype,但| s dtype字符串不能正確地保持unicode

最后,numpy的字符串實際上是可變的,而Python字符串則不是.

>>> z = x.view(np.uint8)
>>> z
array([ 84, 101, 115, 116, 105, 110, 103,  97,  32, 114, 101,  97, 108,
       108, 115, 116, 114, 105, 110, 103,   0], dtype=uint8)
>>> z+=1
>>> x
array([b'Uftujoh', b'b!sfbmm', b'tusjoh\x01'], dtype='|S7')

由於所有這些原因,pandas選擇不允許類似C的固定長度字符串作為數據類型.

正如所注意到的那樣,嘗試將python字符串強制轉換為固定的numpy字符串將無法在pandas中使用.相反,它總是使用本機python字符串,對大多數用戶來說,它的行為更直觀.

 

那為什么np.view可以驗證

NumPy文檔里對ndarray.view方法的說明:

  • ndarray.view(dtype=None, type=None)

  • New view of array with the same data。

  • 返回數據的新視圖。

 

除了view()方法,還有我們熟悉的reshape()方法也可以返回一個視圖,至於其他方法也可以返回視圖

import numpy as np
a = np.arange(10)

b = a.reshape(5,2)

c = a.view()
c.shape = (2,5)

a_base = a.base
b_base = b.base
c_base = c.base
a_base, b_base, c_base
(None,
 array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9]),
 array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9]))

對程序的說明,

  • 首先創建一個具有10個數據的1維數組a,shape為(10, )。

  • b是reshape方法返回的a的一個視圖(view),此時b是一個2維數組,它的shape為(5,2)。

  • c是view方法返回的a的一個視圖,此時c的shape為(10, ),當執行c.shape = (2, 5)后c的shape變為(2, 5)。

  • b_base和c_base說明b和c只是a的一個視圖,共享a的數據,雖然它們的shape各不相同。

接着我們來看看各個數組的base,
>>>a.base is None
True
>>>b.base is a
True
>>>c.base is a
True

如果一個數組的base是None,說明這個數組的數據是自己的,它是這個數據的所有者;如果不是None,則說明數據在不是自己的,他只能通過數據擁有者才能訪問。

如果兩個數組的base相同,說明它們指向同一個數據擁有者。

ndarray.base

  • NumPy文檔說明: Base object if memory is from some other object.

  • base對象說明數據是否來自別的對象。

  • 上面這個例子,a.base是None,說明a自己擁有數據,不是來自別人的,而b和c的base都是a,說明它們都沒有自己的數據,都是a的。

下面代碼的運行結果表明,這三個數組中只有a是數據的所有者,而b和c都不是。

a.flags.owndata, b.flags.owndata, c.flags.owndata
結果:(True, False, False)

驗證:

b[1,1] = 88

把原來的3改成了88。結果我們看下圖,三個數組里的3同時被改成88。

 

 

 
 
       


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM