Python numpy数组添加/更新/删除其他数组中值的行

Python numpy数组添加/更新/删除其他数组中值的行,python,python-3.x,numpy,Python,Python 3.x,Numpy,我有一个numpy数组,根据另一个数组的值,我想更新行的值,或者删除行,或者添加行 例如: 我有arr,一个包含所有值并使用new\u arr中的值进行更新的文件。如果arr中存在new\u arr的第一列中的值,则更新arr的第二列。如果该值不存在,则添加新行。如果new\u arr==0中的第二列,则删除arr中与第一列匹配的行 arr = np.array([[1, 10], [2, 15], [3, 5],

我有一个numpy数组,根据另一个数组的值,我想更新行的值,或者删除行,或者添加行

例如:

我有
arr
,一个包含所有值并使用
new\u arr
中的值进行更新的文件。如果
arr
中存在
new\u arr
的第一列中的值,则更新
arr
的第二列。如果该值不存在,则添加新行。如果
new\u arr==0
中的第二列,则删除
arr
中与第一列匹配的行

arr = np.array([[1, 10],
                [2, 15],
                [3,  5],
                [4, 10]])

new_arr = np.array([[2, 20], # 2 exists in arr and 20 > 0 --> update in arr
                    [5, 20], # 5 does not exists in arr --> add row in arr
                    [1, 0]]) # 1 exists in arr but col 2 == 0--> delete row in arr
那么我想获得:

arr = np.array([[2, 20],
                [3,  5],
                [4, 10],
                [5, 20]])
请注意,
arr
按第一列排序。而且
arr
的最大长度为1000行

请问有什么简单快速的方法吗


最初
arr
new\u arr
是列表。我把它们变成了numpy阵列。但是,由于我没有使用
arr
进行任何强计算,因此很可能将其保留为列表会更快。

您确实需要三种不同的操作,每种操作都很容易实现。添加和删除会分配新的数组,所以您希望一次性批量执行这些操作。因此,您的目标主要是将新数据分成三个部分

首先确定并拆分删除部分:

mask = new_arr[:, -1] == 0
to_del = new_arr[mask, :]
to_add_update = new_arr[~mask, :]
现在,您可以找到添加和更新部分的插入索引:

insert_index = np.searchsorted(arr[:, 0], to_add_update[:, 0])
数组之间插入索引匹配的元素是要更新的位置,而不是要插入的位置。让我们为此定义一个函数,因为我们可以使用它两次:

 def get_insert_update_index(a, v):
     """
     Get new and existing insertion indices.

     Parameters
     ----------
     a :
         The array to insert into.
     v :
         The values to insert

     Returns
     -------
     mask :
         True indicates new elements of `v`.
     insert :
         Insertion indices of new elements in `a`
     update :
         Indices if existing elements in `a`
     """
     index = np.searchsorted(a, v)
     mask = index >= a.size
     mask2 = a[index[~mask]] != v[~mask]
     mask[~mask] = mask2
     return mask, index[mask], index[~mask]

mask, insert_index, update_index = get_insert_update_index(arr[:, 0], to_add_update[:, 0])
如果先处理更新,则索引不会更改:

arr[update_index, -1] = to_add_update[~mask, -1]
处理更新涉及创建新阵列:

arr = np.insert(arr, insert_index, to_add_update[mask, :], axis=0)
现在您已经完成了插入,您将需要重新计算在开始时发现的删除的索引。您可能不想删除不存在的内容,因此
get\u insert\u update\u index
将再次派上用场:

_, _, delete_index = get_insert_update_index(arr[:, 0], to_del[:, 0])
arr = np.delete(are, delete_index, axis=0)

将输入数组保持为numpy构造,下面是我将如何做的

def process_arrays(np1, np2):
    np1d = dict((np1[x][0], np1[x][1]) for x in range(len(np1)))
    np2d = dict((np2[x][0], np2[x][1]) for x in range(len(np2)))
    for ky2 in np2d.keys():
        if ky2 in np1d.keys():
            if np2d[ky2] == 0:
                del np1d[ky2]
            else:
                np1d[ky2] = np2d[ky2]
        else:
            np1d[ky2] = np2d[ky2]
    return np.array(np1d)   
给定您的输入执行:

process_arrays(arr, newArr)  
收益率:

array({2: 20, 3: 5, 4: 10, 5: 20}, dtype=object)

你们能澄清一下你们操纵数组的规则吗:当你们说,若NewArr中的值存在于Arr中,你们是指Arr中的任何地方,仅仅是第1列还是第2列?当你说arr中col 2的值被更新时,它是如何更新的?当你说如果值不存在,你是指newArr中col1的值吗?当你说添加一行时,你的意思是arr吗?当您说如果Newarr的col2=0,则删除arr中的行时,您是指col1==Newarr col1的值的行吗?只有col1与添加或更新相关。因此,如果newArr的第1列中的值存在于arr中,且第2列>0,则我更新第2列。但如果newArr第1列中的值存在于arr中,且第2列=0,则我将删除该值位于arr第1列中的行。如果newArr第1列中的值不存在于arr中,则添加行(按第1列的顺序)。我添加了一些注释以澄清一点。再说一次,如果arr和newArr可以更快的话,它们可能是列表。我相信将值更新为零,然后屏蔽这些条目是更好的方法,但这并不能解决向numpy数组添加条目的问题。你确定字典对你来说不是更好的方法吗?我绝对不是一个numpy专家。但据我所知,删除/添加行/列会迫使numpy重新分配一个新的数组空间并将数据复制到那里。这可能会成为较大数组的问题,因此我建议屏蔽空条目。Numpy数组对于向量化操作来说速度很快,但我知道最好在列表/字典中收集数据,将最终的列表/字典传输到数组中,然后在数组上执行所需的操作。但让我们看看大师们怎么说。附言:你想在numpy数组中使用什么矢量化操作?像这样使用numpy是没有意义的。您创建了一个包含单个字典元素的数组。这只是一种复杂且不必要的开销。那么,itprorh66提出的字典解决方案是最佳解决方案还是基于列表的方法在执行速度方面更具相关性?@NicolasRey,您当然可以用列表替换第二个数组,并遍历列表,而不是遍历第二个dict的键。我不知道性能会有多大差异,它当然会提供一些改进,不必创建第二个dict。我认为将第一个数组转换为dict是一个好主意,因为它允许快速访问元素。