Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/305.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在Python中映射数组的好方法是什么?_Python_Numpy - Fatal编程技术网

在Python中映射数组的好方法是什么?

在Python中映射数组的好方法是什么?,python,numpy,Python,Numpy,我有一个旧的Fortran代码,它将从Python调用 在这段代码中,数据数组是通过某种算法计算的。我简化了它:假设我们有10个元素要处理(在实际应用中,通常是10e+6,而不是10): 然后按如下方式使用这些阵列: my_element = one_of_my_10_elements # does not matter where it comes from my_element_position = elt_position_in_element_id_1 # does not matter

我有一个旧的Fortran代码,它将从Python调用

在这段代码中,数据数组是通过某种算法计算的。我简化了它:假设我们有10个元素要处理(在实际应用中,通常是10e+6,而不是10):

然后按如下方式使用这些阵列:

my_element = one_of_my_10_elements # does not matter where it comes from
my_element_position = elt_position_in_element_id_1 # does not matter how
id_1 = element_id_1[my_element_position]
if id_1 == 0:
   id_2 = None
else:
   id_2 = element_id_2[id_1-1]
   modify(my_element, some_other_data[id_2])
管理这种关系的Pythonic/numpy方法是什么,即获取给定元素的
id_2

我已经看过屏蔽阵列,但还没有找到一种将它们用于此配置的方法。为元素实现一个类,一旦它被计算,它将存储
id_2
,并且只是在以后提供它,这让我想到与数组相比,计算时间非常糟糕。我错了吗

UPD。遗留代码中当前所做工作的一个较大示例:

import numpy as np
number_of_elements = 10

elements = np.arange(number_of_elements, dtype=int)  # my elements IDs
# elements data
# where element_x[7] provides X value for element 7
#   and element_n[7] provides N value for element 7
element_x = np.arange(number_of_elements, dtype=np.float)
element_n = np.arange(number_of_elements, dtype=np.int32)

# array defining subsets of elements
# where
# element_id_1[1] = element_id_1[3] = element_id_1[4] means elements 1, 3 and 4 have something in common
# and
# element_id_1[9] = 0 means element 9 does not belong to any group
element_id_1 = np.array([0, 1, 2, 1, 1, 2, 3, 0, 3, 0])  # size = number_of_elements

# array defining other data for each group of elements
# element_id_2[0] means elements of group 1 (elements 1, 3 and 4) have no data associated
# element_id_2[1] = 1 means elements of group 2 (elements 2 and 5) have data associated: other_x[element_id_2[1]-1] = 7.
# element_id_2[2] = 2 means elements of group 3 (elements 6 and 8) have data associated: other_x[element_id_2[1]-1] = 5.
element_id_2 = np.array([0, 1, 2])  # size = max(element_id_1)
other_x = np.array([7., 5.]) # size = max(element_id_2)

# work with elements
for my_element_position in elements:
    id_1 = element_id_1[my_element_position]

    if id_1 == 0:
        print 'element %d, skipping'%(my_element_position)
        continue

    id_2 = element_id_2[id_1-1]

    if id_2 > 0:
        # use element_x[my_element_position], element_n[my_element_position] and other_x[id_2] to compute more data
        print 'element %d, using other_x[%d] = %f'%(my_element_position, id_2, other_x[id_2-1])
    else:
        # use element_x[my_element_position] and element_n[my_element_position] to compute more data
        print 'element %d, not using other_x'%(my_element_position)
通过切片,我了解到切片一个numpy数组应该比迭代它更快:

elements_to_skip = np.where(element_id_1[:] == 0)[0]
for my_element_position in elements_to_skip:
    print 'element %d, skipping'%(my_element_position)

elements_with_id1 = np.where(element_id_1[:] > 0)[0]
array1 = element_id_1[elements_with_id1]
array1 = element_id_2[array1-1]
array1 = np.where(array1[:] > 0)[0]
elements_with_data = elements_with_id1[array1]
id_2_array = element_id_2[element_id_1[elements_with_data]-1]
for my_element_position, id_2 in zip(elements_with_data, id_2_array):
    print 'element %d, using other_x[%d] = %f'%(my_element_position, id_2, other_x[id_2-1])

elements_without_data = np.delete(elements, np.concatenate((elements_to_skip, elements_with_data)))
for my_element_position in elements_without_data:
    print 'element %d, not using other_x'%(my_element_position)

这将给出与上面代码片段相同的结果。你有没有发现一种方法可以让这段不可读的代码变得更好?与前面的代码片段相比,这种方法是否更值得推荐?

如果我有类似的问题,我会选择hashMapsdict与大多数语言中的hashMap几乎相同。
有关详细信息,请查看: 比如:

id2_dict = {}
my_element = one_of_my_10_elements # does not matter where it comes from
my_element_position = elt_position_in_element_id_1 # does not matter how
id_1 = element_id_1[my_element_position]
if id_1 == 0:
   id2_dict[id_1] = None
else:
   id2_dict[id_1] = id2_dict[id_1-1]
考虑到数据(整数)的性质,您可能希望使用
列表
,但如果您的id_1值是稀疏的,则会浪费大量空间,并且采用的pythonic方法会更少。但是如果您的id_1值跨越一个整数范围,并且在某些范围内密集,那么使用一个列表并相应地处理索引。列表将为您节省哈希部分,但会使其不太像Python,更难维护。

tl;dr:如果id_1密集且几乎跨越一个范围,则使用
列表和id_1作为索引(进行一些索引移动),否则使用(hashmap)
dict
和id_1作为键。

我不完全确定您的代码需要做什么,但我认为,如果您使用numpy数组,您需要这样做:

number_of_elements = 10
element_id_1 = np.array([0, 1, 2, 1, 1, 2, 3, 0, 3, 0]) 
element_id_2 = np.array([np.NaN,0, 1, 2]  )
# to get the  "elemtn_id_1 th" elemnt from element_id_2
result=element_id_2[element_id_1]
我使用np.NaN而不是None如果您不想在结果中使用np.NaN,只需执行以下操作:

result[np.logical_not(np.isnan(result))]
编辑:根据您的示例代码,与我所做的一样,您只需为案例0和1分配不同的其他\u x,然后从数组中提取所需内容:

element_id_1 = np.array([0, 1, 2, 1, 1, 2, 3, 0, 3, 0])

data=array([np.NaN,-1,7,5])

result=data[element_id_1]

print "skipping:"+str(np.where(np.isnan(result)))

print "using other data:"+str(np.where(nan_to_num(result)>0))
print "other data used:"+str(result[nan_to_num(result)>0])

print "not using other data:"+str(np.where(result==-1))
返回:

skipping:(array([0, 7, 9]),)
using other data:(array([2, 5, 6, 8]),)
other data used:[ 7.  7.  5.  5.]
not using other data:(array([1, 3, 4]),)

如果您不喜欢NaN,也可以通过在这种情况下指定-2来省略它们。

谢谢@Kamyar Ghasemlou,我会看看的。数组内容始终是0到N之间的非负整数,0到N之间的每个值在数组中至少出现两次。在大多数情况下,元素_id_1中会有很多零。因此,您将有很多重复的键/索引,您计划如何处理它们?覆盖上一个值还是保留最大/最小值?如果在id_2 dict中有很多零,只需不添加任何内容,如果键不存在,则值将为零。这将为您节省大量空间,但会降低性能。是的,您是对的。我将对这两种方法进行原型化,以便分析代码性能,并确定我应该优先考虑哪种方法。非常感谢你的深思熟虑!不客气,我希望你能找到一个优雅的解决方案。如果您能选择被接受的答案,我将不胜感激,当然,如果它有用的话。:)谢谢@user1901493。至少对于np.NaN的提示我没有想到。这会有用的。这比根据第一个数组中的值从第二个数组中获取数据要多得多。已经有一个“隐式”元素数组,实际上是元素的索引。我在问题中添加了一个更新的示例。总结一下:您希望重新映射一个数组,用给定的替换值集替换该数组中给定的值子集;对吗?
skipping:(array([0, 7, 9]),)
using other data:(array([2, 5, 6, 8]),)
other data used:[ 7.  7.  5.  5.]
not using other data:(array([1, 3, 4]),)