2017-03-09 74 views
-1

我问这个问题的主要原因是因为我不完全知道结构化数组与正常数组相比是如何工作的,因为我找不到适合我的案例。而且,我可能首先错误地填充了我的结构化数组。PYTHON/NUMPY:处理与普通numpy数组相比较的结构化数组Python2.7

所以,在这里,我想提出'普通'numpy阵列版本(以及我需要做的)和新的'结构化'阵列版本。我的(最大的)数据集包含大约200e6个对象/行,最多40-50个属性/列。它们都有相同的数据类型,除了一些特殊的列:'haloid','hostid','type'。他们是身份证号码或国旗,我必须保留其余的数据,因为我必须与他们识别我的对象。

数据集名:

data_array: ndarray shape: (42648, 10) 

数据类型:从.hdf5文件格式

dt = [('haloid', '<u8'), ('hostid', '<u8'), ('type', 'i1'), 
('mstar', '<f8'), ('x_pos', '<f8'), ('y_pos', '<f8'), 
('z_pos', '<f8'), ('x_vel', '<f8'), ('y_vel', '<f8'), ('z_vel', '<f8')] 

读数据到阵列

大部分数据被存储在hdf5-文件(它们中的2000个对应于我必须一次处理的一个快照),其应该被读入到单个阵列中

import numpy as np 
import h5py as hdf5 

mydict={'name0': 'haloid', 'name1': 'hostid', ...} #dictionary of column names 
nr_rows  = 200000        # approximated 
nr_files = 100         # up to 2200 
nr_entries = 10         # up to 50 
size  = 0 
size_before = 0 
new_size = 0 

# normal array: 
data_array=np.zeros((nr_rows, nr_entries), dtype=np.float64) 
# structured array: 
data_array=np.zeros((nr_rows,), dtype=dt) 

i=0 
while i<nr_files: 
    size_before=new_size 

    f = hdf5.File(path, "r") 
    size=f[mydict['name0']].size 

    new_size+=size     

    a=0 
    while a<nr_entries: 
     name=mydict['name'+str(a)] 
     # normal array: 
     data_array[size_before:new_size, a] = f[name] 
     # structured array: 
     data_array[name][size_before:new_size] = f[name]     
     a+=1     
    i+=1 

编辑:我修改上面的代码,因为hpaulj是幸运的评论如下:混乱的

第一点。您显示一个名称为dt = [('haloid', '<u8'), ('hostid', '<u8'), ('type', 'i1'),....的dt定义,但是 的h5加载为 data_array ['name'+ str(a)] [size_before:new_size] = f ['name'+ str(a)]换句话说,文件具有名称类似name0,name1, 的数据集,并且您将这些数据集下载到数组中,其名称相同的 。

这是一个 'I-简化代码' 复制/粘贴错误,我纠正它

问题1:这是填补结构化数组的正确方法吗?

data_array[name][size_before:new_size] = f[name] 

问题2:如何解决结构化阵列列?

data_array[name] #--> column with a certain name 

问题3:如何解决在结构数组一整行?

data_array[0] #--> first row 

问题4:如何解决3行中的所有列?

# normal array: 
print data_array[0:3,:] 
[[ 1.21080866e+10 1.21080866e+10 0.00000000e+00 5.69363234e+08 
    1.28992369e+03 1.28894614e+03 1.32171442e+03 -1.08210000e+02 
    4.92900000e+02 6.50400000e+01] 
[ 1.21080711e+10 1.21080711e+10 0.00000000e+00 4.76329837e+06 
    1.29058079e+03 1.28741361e+03 1.32358059e+03 -4.23130000e+02 
    5.08720000e+02 -6.74800000e+01] 
[ 1.21080700e+10 1.21080700e+10 0.00000000e+00 2.22978043e+10 
    1.28750287e+03 1.28864306e+03 1.32270418e+03 -6.13760000e+02 
    2.19530000e+02 -2.28980000e+02]] 

# structured array:  
print data_array[0:3] 
#it returns a lot of data ... 
[[ (12108086595L, 12108086595L, 0, 105676938.02998888, 463686295.4907876,.7144191943337, -108.21, 492.9, 65.04) 
    (12108071103L, 12108071103L, 0, 0.0, ... more data ... 
    ... 228.02) ... more data ... 
    (8394715323L, 8394715323L, 2, 0.0, 823505.2374262045, 0798, 812.0612163877823, -541.61, 544.44, 421.08)]] 

问题5:为什么data_array[0:3]不仅返回第3行与10列?

问题6:如何解决第一列中的前两个元素?

# normal array: 
print data_array[0:1,0] 
[ 1.21080866e+10 1.21080711e+10] 
# structured array: 
print data_array['haloid']][0][0:1] 
[12108086595 12108071103] 

行!我明白了!

问题7:如何通过名称解决三个特定的列,他们在该列的前3行?

# normal array: 
print data_array[0:3, [0,2,1]] 
[[ 1.21080866e+10 0.00000000e+00 1.21080866e+10] 
[ 1.21080711e+10 0.00000000e+00 1.21080711e+10] 
[ 1.21080700e+10 0.00000000e+00 1.21080700e+10]] 

# structured array: 
print data_array[['haloid','type','hostid']][0][0:3] 
[(12108086595L, 0, 12108086595L) (12108071103L, 0, 12108071103L) 
(12108069992L, 0, 12108069992L)] 

好的,最后一个例子似乎工作!

问题8:之间有什么区别:

(一)data_array['haloid'][0][0:3]和(b)data_array['haloid'][0:3]

其中(一)返回真前三haloids和(b)返回了很多卤素(10x3)。

[[12108086595 12108071103 12108069992 12108076356 12108075899 12108066340 
    9248632230 12108066342 10878169355 10077026070] 
[ 6093565531 10077025463 8046772253 7871669276 5558161476 5558161473 
    12108068704 12108068708 12108077435 12108066338] 
[ 8739142199 12108069995 12108069994 12108076355 12108092590 12108066312 
    12108075900 9248643751 6630111058 12108074389]] 

问题9:什么是data_array['haloid'][0:3]实际上返回?

问题10:如何屏蔽结构阵列np.where()

# NOTE: col0,1,2 are some integer values of the column I want to address 
# col_name0,1,2 are corresponding names e.g. mstar, type, haloid 

# normal array 
mask = np.where(data[:,col2] > data[:,col1]) 
data[mask[:][0]] 

mask = np.where(data[:,col2]==2) 
data[:,col0][[mask[:][0]]]=data[:,col2][[mask[:][0]]] 

#structured array 
mask = np.where(data['x_pos'][0] > data['y_pos'][0]]) 
data[mask[:][0]] 

mask = np.where(data[:,col2]==2) 
data['haloid'][:,col0][[mask[:][0]]]=data['hostid'][:,col1][[mask[:][0]]] 

这似乎是工作,但我不知道!

问题11:我还可以使用np.resize(),如:data_array = np.resize(data_array,(new_size, nr_entries))调整大小/重塑我的阵列?

问题12:如何排序结构化数组?

# normal array: 
data_sorted = data[np.argsort(data[:,col2])] 
# structured array: 
data_sorted = data[np.argsort(data['mstar'][:,col3])] 

谢谢,我感谢任何帮助或建议!

+0

X [0] [0:3]从行0返回前三列。 X [0:3]返回前三行的所有列 – valentin

+0

@valentin:嗨,感谢您的评论!我不确定,当我打印data_array ['haloid'] [0:3]时,我得到(3,10),但所有列,但只有'卤素的回报(不知道他们来自哪里!)。请再次看到问题,我添加了data_array ['haloid'] [0:3]的输出。 – firefly2517

+0

我只是剔除了你的问题,但我想知道为什么不能将id值保存为相同长度的单独数组?将1d数组作为一个字段搜索一样简单。它是否有助于尝试一个小例子,并且没有'h5py'部分?如果我写回答,将会用一个非常小的例子来说明。 – hpaulj

回答

1

第一点混淆。您可以用dt = [('haloid', '<u8'), ('hostid', '<u8'), ('type', 'i1'),...这样的名称显示一个dt的定义。但h5负荷 是

data_array['name'+str(a)][size_before:new_size] = f['name'+str(a)] 

换句话说,该文件有数据集与像name0name1的名字,而你下载这些与具有相同名称的字段的数组。

可以使用

for name in dt.names: 
    data[name] = ... 

例如迭代的阵列与dt定义的字段的

In [20]: dt = [('haloid', '<u8'), ('hostid', '<u8'), ('type', 'i1'), 
    ...: ('mstar', '<f8'), ('x_pos', '<f8'), ('y_pos', '<f8'), 
    ...: ('z_pos', '<f8'), ('x_vel', '<f8'), ('y_vel', '<f8'), ('z_vel', '<f8')] 
In [21]: arr = np.zeros((3,), dtype=dt) 
In [22]: arr 
Out[22]: 
array([(0, 0, 0, 0., 0., 0., 0., 0., 0., 0.), 
     (0, 0, 0, 0., 0., 0., 0., 0., 0., 0.), 
     (0, 0, 0, 0., 0., 0., 0., 0., 0., 0.)], 
     dtype=[('haloid', '<u8'), ('hostid', '<u8'), ('type', 'i1'), ('mstar', '<f8'), ('x_pos', '<f8'), ('y_pos', '<f8'), ('z_pos', '<f8'), ('x_vel', '<f8'), ('y_vel', '<f8'), ('z_vel', '<f8')]) 
In [23]: for name in arr.dtype.names: 
    ...:  print(name) 
    ...:  arr[name] = 1 
    ...:  
haloid 
hostid 
.... 
In [24]: arr 
Out[24]: 
array([(1, 1, 1, 1., 1., 1., 1., 1., 1., 1.), 
     (1, 1, 1, 1., 1., 1., 1., 1., 1., 1.), 
     (1, 1, 1, 1., 1., 1., 1., 1., 1., 1.)], 
     dtype=[('haloid', '<u8'), ('hostid', '<u8'), ('type', 'i1'), ('mstar', '<f8'), ('x_pos', '<f8'), ('y_pos', '<f8'), ('z_pos', '<f8'), ('x_vel', '<f8'), ('y_vel', '<f8'), ('z_vel', '<f8')]) 
In [25]: arr[0]  # get one record 
Out[25]: (1, 1, 1, 1., 1., 1., 1., 1., 1., 1.) 
In [26]: arr[0]['hostid']  # get one field, one record 
In [27]: arr['hostid']  # get all values of a field 
Out[27]: array([1, 1, 1], dtype=uint64) 
In [28]: arr['hostid'][:2] # subset of records 
Out[28]: array([1, 1], dtype=uint64) 

因此,通过字段名填充结构数组应该很好地工作:

arr[name][n1:n2] = file[dataset_name] 

打印这样的:

结构数组:
打印data_array中[ '哈罗依德',” (12108071103L,0,12108071103L)(12108069992L,0,12108069992L)][(12108086595L,0,12108081095L)][(12108086595L,0,12108081095L)]

[[(12108086595L,12108086595L,0,

看我像结构化data_array实际上是2D,喜欢的东西创建(见问题8)

data_array = np.zeros((10, nr_rows), dtype=dt) 

这是[0][0:3]索引工作的唯一途径,

用于2D阵列:

mask = np.where(data[:,col2] > data[:,col1]) 

比较2列。如有疑问,请首先查看布尔型data[:,col2] > data[:,col1]where只是返回布尔数组为True的索引。掩蔽索引

简单的例子:

In [29]: x = np.array((np.arange(6), np.arange(6)[::-1])).T 
In [33]: mask = x[:,0]>x[:,1] 
In [34]: mask 
Out[34]: array([False, False, False, True, True, True], dtype=bool) 
In [35]: idx = np.where(mask) 
In [36]: idx 
Out[36]: (array([3, 4, 5], dtype=int32),) 
In [37]: x[mask,:] 
Out[37]: 
array([[3, 2], 
     [4, 1], 
     [5, 0]]) 
In [38]: x[idx,:] 
Out[38]: 
array([[[3, 2], 
     [4, 1], 
     [5, 0]]]) 

在这种结构化的例子,data['x_pos']选择场。需要[0]才能选择该2d阵列的第一行(尺寸为10的尺寸)。比较的其余部分和哪里应该与2d数组一样工作。

mask = np.where(data['x_pos'][0] > data['y_pos'][0]]) 

where元组mask[:][0]可能是没有必要的。 mask是一个元组,[:]创建一个副本,[0]选择第一个元素,它是一个数组。有时可能需要arr[idx[0],:]而不是arr[idx,:],但不要经常这样做。

我的第一个评论所说独立阵列

dt1 = [('haloid', '<u8'), ('hostid', '<u8'), ('type', 'i1')] 
data_id = np.zeros((n,), dtype=dt1) 

data = np.zeros((n,m), dtype=float) # m float columns 

甚至

haloid = np.zeros((n,), '<u8') 
hostid = np.zeros((n,), '<u8') 
type = np.zeros((n,), 'i1') 

有了这些阵列,data_array['hostid'][0]data_id['hostid']hostid都应该返回相同的一维数组,并且在mask表达同样可用。

有时将ID和数据保存在一个结构中很方便。如果写入/读取格式文件为csv,则尤其如此。但对于蒙面选择,这并没有太大的帮助。而对于跨数据字段的数据计算,这可能是一个痛苦。

我也可以提出一个复合D型细胞,一个带有

dt2 = [('haloid', '<u8'), ('hostid', '<u8'), ('type', 'i1'), ('data', 'f8', (m,))] 

In [41]: np.zeros((4,), dtype=dt2) 
Out[41]: 
array([(0, 0, 0, [ 0., 0., 0.]), (0, 0, 0, [ 0., 0., 0.]), 
     (0, 0, 0, [ 0., 0., 0.]), (0, 0, 0, [ 0., 0., 0.])], 
     dtype=[('haloid', '<u8'), ('hostid', '<u8'), ('type', 'i1'), ('data', '<f8', (3,))]) 
In [42]: _['data'] 
Out[42]: 
array([[ 0., 0., 0.], 
     [ 0., 0., 0.], 
     [ 0., 0., 0.], 
     [ 0., 0., 0.]]) 

是更好的列数或像“x_coor”的名称来访问浮点数据?您是否需要一次对多个浮动列进行计算,或者您是否总是单独访问它们?

+0

非常感谢!令人惊讶的是,你真的救了我,现在我开始将你的意见应用到我的程序中! – firefly2517

+0

您的评论“换句话说,该文件具有名称类似name0,name1的数据集,并且您正在将这些数据下载到具有相同名称的字段的数组中。”这是一个错字,它应该只在你评论时说'名字'。我会在问题中编辑它! – firefly2517

0

通过你的描述,我认为幼稚的方法是阅读的唯一有用的数据与不同的名称阵列(?一类各也许) 如果你想读入一个数组中的所有数据,也许大熊猫是你的选择: http://pandas.pydata.org http://pandas.pydata.org/pandas-docs/stable/ 但我还没有尝试过。玩得开心,试试看。

+0

嗨,感谢您的评论:我只是在阅读我所需要的数据。我必须将其过滤并将它们一起存储在更方便的子文件中。但是,身份证号码至关重要,我必须将其与其余数据一起存储... – firefly2517

+0

不需要保存其他阵列的1D号码。 排序的数组或片可应用于不同的阵列 例如: IDs =晕ID;数组=你的数组; sorted_a1 = np.argsort(arrays [:,1]) ID [sorted_a1]与数组[sorted_a1,1]具有相同的顺序 np.where() – frog

+0

同样适用于片段,'mstar '然后将对象A的'x_pos'设置为对象B的'x_pos',其中来自对象A的'hostid'是对象B''的'haloid'?我需要通过卤素来识别它们,还是我想念这里的东西? – firefly2517

0

回答问题11:

问题11:我仍然可以使用np.resize(),如:data_array中= np.resize(data_array中,(new_size,nr_entries))调整/重塑我的 数组?

如果我正在调整我的数组的大小,我正在为每个字段创建dt另外10列。所以我得到'奇怪的结果问题8b:一个结构(10x3)的haloids

正确的方式来修剪我的数组,因为我只想保留填充的部分if(我设计的数组是大到足以包含我随后读取的各种数据块...)是:

data_array = data_array[:newsize] 

print np.info(data_array) 

class: ndarray 
shape: (42648,) 
strides: (73,) 
type: [('haloid', '<u8'), ('hostid', '<u8'), ('orphan', 'i1'), 
('mstar', '<f8'), ('x_pos', '<f8'), ('y_pos', '<f8'), 
('z_pos', '<f8'), ('x_vel', '<f8'), ('y_vel', '<f8'), ('z_vel', '<f8')]