簡體   English   中英

字符串格式問題(括號與下划線)

[英]String formatting issue (parantheses vs underline)

我得到了一個包含我所有數據的文本文件

data = 'B:/tempfiles/bla.dat'

從文本文件中,我列出了列標題及其類型

col_headers = [('VW_3_Avg','<f8'),('Lvl_Max(1)','<f8')]

然后創建一個包含選項的字典變量:

kwargs = dict(delimiter=',',\
              deletechars=' ',\
              dtype=col_headers,\
              skip_header=4,\
              skip_footer=0,\
              filling_values='NaN',\
              missing_values={'\"NAN\"'}\
              )

現在將數據導入變量數據文件

datafile = scipy.genfromtxt(datafile, **kwargs)

然后我分配數據

VW1 = datafile['VW_3_Avg']
Lv1 = datafile['Lvl_Max(1)']

它適用於第一個(包含下划線),而不是第二個(括號)。 我得到一個錯誤,不僅是這個條目,還有所有包含括號的:

ValueError: field named Lvl_Max(1) not found 

當我將文本文件中的那些括號更改為下划線時,它運行良好。 但我不能說為什么它不允許我使用括號——而且我無法更改文本文件格式,因為這是在外部生成的。 當然,我可以用腳本將括號更改為下划線,但我認為正確處理應該不是什么大問題。 在這種情況下,我在哪里以及為什么缺少正確的格式優先級?

當您遇到genfromtxt問題時,您應該做的第一件事就是打印shapedtype

為什么你需要使用()col_headers = [('VW_3_Avg','<f8'),('Lvl_Max(1)','<f8')]

是因為文件在標題中有這些名稱嗎?

如果你是給自己的dtype ,並使用skip_header不要緊什么上的文件。 重要的是dtype中的字段名稱,而不是文件中的字段名稱。

我們可以深入研究dtype文檔並找到允許使用的字符。 可以用作 Python 變量名稱的字段名稱肯定會起作用。 我並不驚訝()會被禁止或有問題,盡管我還沒有測試過。


實際上'Lvl_Max(1)'作為 dtype 字段名稱是可以接受的:

In [235]: col_headers = [('VW_3_Avg','<f8'),('Lvl_Max(1)','<f8')]
In [236]: A=np.zeros((3,),dtype=col_headers)
In [237]: A
Out[237]: 
array([(0.0, 0.0), (0.0, 0.0), (0.0, 0.0)], 
      dtype=[('VW_3_Avg', '<f8'), ('Lvl_Max(1)', '<f8')])
In [238]: A['Lvl_Max(1)']
Out[238]: array([ 0.,  0.,  0.])

您應該從一開始就向我們展示datafile.shapedatafile.dtype 這些genfromtxt問題中有 90% 源於對函數返回的誤解。


讓我們用這個 dtype 嘗試一個簡單的文件讀取:

In [239]: txt=b"""1 2
   .....: 3 4
   .....: 5 6
   .....: """
In [240]: np.genfromtxt(txt.splitlines(),dtype=col_headers)
Out[240]: 
array([(1.0, 2.0), (3.0, 4.0), (5.0, 6.0)], 
      dtype=[('VW_3_Avg', '<f8'), ('Lvl_Max1', '<f8')])

看看dtype genfromtxt去掉了'(1)' 看起來genfromtxt '清理'了字段名稱,毫無疑問,因為文本文件上的名稱可能有各種有趣的東西。

genfromtxt文檔:

具有結構化 dtype 的 Numpy 數組也可以被視為 recarray,其中可以像訪問屬性一樣訪問字段。 出於這個原因,我們可能需要確保字段名稱不包含任何空格或無效字符,或者它不對應於標准屬性的名稱(如大小或形狀),這會混淆解釋器。


genfromtxt接受一個deletechars參數,它應該讓您控制從字段名稱中刪除哪些字符。 但它的應用是不一致的。

In [282]: np.genfromtxt(txt.splitlines(),names=np.dtype(col_headers).names,deletechars=set(b' '),dtype=None)
Out[282]: 
array([(1, 2), (3, 4), (5, 6)], 
      dtype=[('VW_3_Avg', '<i4'), ('Lvl_Max(1)', '<i4')])

In [283]: np.genfromtxt(txt.splitlines(),names=np.dtype(col_headers).names,deletechars=set(b' '))
Out[283]: 
array([(1.0, 2.0), (3.0, 4.0), (5.0, 6.0)], 
      dtype=[('VW_3_Avg', '<f8'), ('Lvl_Max1', '<f8')])

dtype=None是必需的。

默認設置很大:

defaultdeletechars = set("""~!@#$%^&*()-=+~\|]}[{';: /?.>,<""")

問題是deletechars傳遞給validator

validate_names = NameValidator(...
                               deletechars=deletechars,...)

它用於清除標題和names參數中的names 但隨后名稱(和 dtype)被傳遞

dtype = easy_dtype(dtype, defaultfmt=defaultfmt, names=names)

沒有deletechars參數。 這個問題大約在一年前解決, https://github.com/numpy/numpy/pull/4649 ,所以可能會在新的(est)版本中修復。

該行為被記錄在案, lib/_iotools.pyNameValidator類解析傳遞給genfromtxt的名稱:

class NameValidator(object):
    """
    Object to validate a list of strings to use as field names.
    The strings are stripped of any non alphanumeric character, and spaces
    are replaced by '_'. During instantiation, the user can define a list
    of names to exclude, as well as a list of invalid characters. Names in
    the exclusion list are appended a '_' character.
    Once an instance has been created, it can be called with a list of
    names, and a list of valid names will be created.  The `__call__`
    method accepts an optional keyword "default" that sets the default name
    in case of ambiguity. By default this is 'f', so that names will
    default to `f0`, `f1`, etc.

您的情況的相關行是The strings are stripped of any non alphanumeric character

您可以通過在名稱中包含其他非字母數字字符的列表上調用NameValidator.validate來查看行為:

In [17]: from numpy.lib._iotools import NameValidator

In [18]: l = ["foo(1)","bar!!!","foo bar??"]

In [19]: NameValidator().validate(l)
Out[19]: ('foo1', 'bar', 'foo_bar')

同樣使用 genfromtxt:

In [24]: datafile = np.genfromtxt("foo.txt", dtype=[('foo!! bar??', '<f8'), ('foo bar bar$', '<f8')], delimiter=",",defaultfmt="%")

In [25]: datafile.dtype
Out[25]: dtype([('foo_bar', '<f8'), ('foo_bar_bar', '<f8')])

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM