向结构化的numpy数组添加字段(4)

时间:2018-11-04 04:45:25

标签: python arrays numpy

此问题已在(hereherehere)之前解决。我想向numpy genfromtxt(也问here)返回的结构数组中添加一个新字段。

我的新问题是我正在读取的csv文件只有标题行和单个数据行:

output-Summary.csv

Wedge, DWD, Yield (wedge), Efficiency
1, 16.097825, 44283299.473156, 2750887.118836

我正在通过genfromtxt进行读取,并计算出一个新值'tl'

test_out = np.genfromtxt('output-Summary.csv', delimiter=',', names=True)
tl = 300 / test_out['DWD']

test_out看起来像这样:

array((1., 16.097825, 44283299.473156, 2750887.118836),
      dtype=[('Wedge', '<f8'), ('DWD', '<f8'), ('Yield_wedge', '<f8'), ('Efficiency', '<f8')])

使用recfunctions.append_fields(如上面的示例1-3中所述)无法对大小为1的数组使用len()

from numpy.lib import recfunctions as rfn
rfn.append_fields(test_out,'tl',tl)

TypeError: len() of unsized object

搜索替代项(答案here之一),我发现mlab.rec_append_fields效果很好(但已弃用):

mlab.rec_append_fields(test_out,'tl',tl)

C:\ProgramData\Anaconda3\lib\site-packages\ipykernel_launcher.py:1: MatplotlibDeprecationWarning: The rec_append_fields function was deprecated in version 2.2.
  """Entry point for launching an IPython kernel.
rec.array((1., 16.097825, 44283299.473156, 2750887.118836, 18.63605798),
          dtype=[('Wedge', '<f8'), ('DWD', '<f8'), ('Yield_wedge', '<f8'), ('Efficiency', '<f8'), ('tl', '<f8')])

我也可以按照建议here手动将阵列复制到新的结构化阵列。这有效:

test_out_new = np.zeros(test_out.shape, dtype=new_dt)
for name in test_out.dtype.names:
    test_out_new[name]=test_out[name]
test_out_new['tl']=tl

因此,总而言之,有没有一种方法可以使recfunctions.append_fields与我的单行csv文件的genfromtxt输出配合使用? 我真的更愿意使用一种标准的方式来处理此问题,而不是使用家庭酿造方法。

1 个答案:

答案 0 :(得分:2)

将数组(和新字段)重塑为大小(1,)。 genfromtxt仅用一行,就将数据加载为0d数组,形状为()。 rfn代码并未得到广泛使用,并且也不如应有的健壮性。换句话说,“标准方式”还是有点问题。

例如:

In [201]: arr=np.array((1,2,3), dtype='i,i,i')
In [202]: arr.reshape(1)
Out[202]: array([(1, 2, 3)], dtype=[('f0', '<i4'), ('f1', '<i4'), ('f2', '<i4')])

In [203]: rfn.append_fields(arr.reshape(1), 't1',[1], usemask=False)
Out[203]: 
array([(1, 2, 3, 1)],
      dtype=[('f0', '<i4'), ('f1', '<i4'), ('f2', '<i4'), ('t1', '<i8')])

home_brew没问题。大多数rfn函数使用该机制-定义一个新的dtype,使用该dtype创建一个收件人数组,然后按名称逐个复制字段。