Numpy,将列添加到现有结构化数组

时间:2014-08-21 13:09:37

标签: python python-2.7 numpy structured-array

我有一个起始数组:

[(1, [-112.01268501699997, 40.64249414272372])
 (2, [-111.86145708699996, 40.4945008710162])]

其中第一列是int,第二列是带有浮点数的元组。我需要添加一个名为USNG的字符串列。

然后我创建一个结构化的numpy数组:

dtype = numpy.dtype([('USNG', '|S100')])
x = numpy.empty(array.shape, dtype=dtype)

我想将x numpy数组附加到现有数组以添加新列,以便我可以为每一行输出一些信息。当我执行以下操作时:

numpy.append(array, x, axis=1)# I've also tried vstack and hstack

我收到以下错误:

'TypeError: invalid type promotion'

有关为何发生这种情况的任何建议?

由于

5 个答案:

答案 0 :(得分:7)

您必须创建一个包含新字段的新dtype。

例如,这里a

In [86]: a
Out[86]: 
array([(1, [-112.01268501699997, 40.64249414272372]),
       (2, [-111.86145708699996, 40.4945008710162])], 
      dtype=[('i', '<i8'), ('loc', '<f8', (2,))])

a.dtype.descr[('i', '<i8'), ('loc', '<f8', (2,))];即字段类型列表。我们通过将('USNG', 'S100')添加到该列表的末尾来创建新的dtype:

In [87]: new_dt = np.dtype(a.dtype.descr + [('USNG', 'S100')])

现在创建一个 new 结构化数组b。我在这里使用zeros,因此字符串字段将以值''开头。您也可以使用empty。然后字符串将包含垃圾,但如果您立即为它们分配值,则无关紧要。

In [88]: b = np.zeros(a.shape, dtype=new_dt)

将现有数据从a复制到b

In [89]: b['i'] = a['i']

In [90]: b['loc'] = a['loc']

此处b现在:

In [91]: b
Out[91]: 
array([(1, [-112.01268501699997, 40.64249414272372], ''),
       (2, [-111.86145708699996, 40.4945008710162], '')], 
      dtype=[('i', '<i8'), ('loc', '<f8', (2,)), ('USNG', 'S100')])

使用一些数据填写新字段:

In [93]: b['USNG'] = ['FOO', 'BAR']

In [94]: b
Out[94]: 
array([(1, [-112.01268501699997, 40.64249414272372], 'FOO'),
       (2, [-111.86145708699996, 40.4945008710162], 'BAR')], 
      dtype=[('i', '<i8'), ('loc', '<f8', (2,)), ('USNG', 'S100')])

答案 1 :(得分:2)

您是否尝试过使用numpy的refunctions?

import numpy.lib.recfunctions as rfn

它对结构化数组具有一些非常有用的功能。

对于您的情况,我认为可以通过以下方式实现:

a = rfn.append_fields(a, 'USNG', np.empty(a.shape[0], dtype='|S100'), dtypes='|S100')

在这里进行了测试,并且有效。


merge_arrays

如GMSL在评论中所述。可以使用rfn.merge_arrays如下所示:

a = np.array([(1, [-112.01268501699997, 40.64249414272372]),
       (2, [-111.86145708699996, 40.4945008710162])], 
      dtype=[('i', '<i8'), ('loc', '<f8', (2,))])
a2 = np.full(a.shape[0], '', dtype=[('USNG', '|S100')])
a3 = rfn.merge_arrays((a, a2), flatten=True)

a3将具有以下值:

array([(1, [-112.01268502,   40.64249414], b''),
       (2, [-111.86145709,   40.49450087], b'')],
      dtype=[('i', '<i8'), ('loc', '<f8', (2,)), ('USNG', 'S100')])

答案 2 :(得分:1)

  1. 使用pandas.DataFramepandas.DataFrame.from_records读取当前的recarray
  2. 将新的数据列添加到数据框
  3. 使用pandas.DataFrame.to_records将数据框导出到recarray
import pandas as pd
import numpy as np

# current recarray
data = np.rec.array([(1, list([-112.01268501699997, 40.64249414272372])), (2, list([-111.86145708699996, 40.4945008710162]))], dtype=[('i', '<i8'), ('loc', 'O')])

# create dataframe
df = pd.DataFrame(data)

# display(df)
   i                                       loc
0  1  [-112.01268501699997, 40.64249414272372]
1  2   [-111.86145708699996, 40.4945008710162]

# add new column
df['USNG'] = ['Note 1', 'Note 2']

# display(df)
   i                                       loc    USNG
0  1  [-112.01268501699997, 40.64249414272372]  Note 1
1  2   [-111.86145708699996, 40.4945008710162]  Note 2

# write the dataframe to recarray
data = df.to_records(index=False)

print(data)
[out]:
rec.array([(1, list([-112.01268501699997, 40.64249414272372]), 'Note 1'),
           (2, list([-111.86145708699996, 40.4945008710162]), 'Note 2')],
          dtype=[('i', '<i8'), ('loc', 'O'), ('USNG', 'O')])

答案 3 :(得分:0)

问题恰恰是:&#34;有关为何发生这种情况的任何建议?&#34;

从根本上说,这是bug ---自2012年以来它一直是numpy的门票。

答案 4 :(得分:0)

Tonicic在df1 = df.groupby('ID',as_index=False,sort=False).last() 中提到了重新功能。在这种情况下,import numpy.lib.recfunctions as rfndocs)是最适合您的简化功能。