numpy将重复值替换为0

htzpubme  于 9个月前  发布在  其他
关注(0)|答案(4)|浏览(145)

我有两个数组,看起来像这样:

arr1 = [0 1 0 0 0 0 0 0 0 0 0 0 0 0 1 1 0 0 0 0 1 0 0 1 1 1 1 1 1 1 0 1 0 1 0 0 1
 1 0 0 0 0 0 1 1 0 1 0 0 0 0 0 0 0 0 0 1 1 0 0 1 0 0 1 0 0 0 1 1 1 1 1 0 0
 1 1 1 1 0 0 0 1 0 1 1 0 1 1 0 0 0 0 0 1 1 1 1 0 1 0]
arr2 = [0 0 0 0 1 1 1 0 1 1 1 0 1 0 0 1 0 1 1 1 0 1 1 0 0 0 0 0 0 0 0 1 0 0 0 1 0
 0 0 0 1 1 1 0 0 0 0 0 0 1 0 1 1 0 1 1 0 0 0 1 0 0 1 0 1 1 1 0 0 1 0 0 0 1
 0 0 0 1 1 1 1 0 0 1 0 1 0 0 1 1 1 1 1 0 0 0 1 1 0 0]

字符串
1.比较两个数组的最快方法是什么?如果两个数组在相同的位置都有“1”,找出哪个数组有最接近的“0”,并将该数组中的“1”替换为“0”。
1.用“0”替换数组中后跟“1”的所有“1“。
我使用迭代解决了这个问题,但我相信在numpypandas中有一个简单且更快的解决方案,我才刚刚开始学习。
这里有一个使用迭代解决第一个问题的丑陋示例:

df = pd.DataFrame({"A": arr1, "B": arr2, })
    df2 = df[(df.A > 0) & (df.B > 0)]
    i = 1
    for idx in df2.index:
        while df.loc[idx, 'A'] == 1 and df.loc[idx, 'B'] == 1:
            try:
                if df.loc[idx - i, 'A'] > 0 or df.loc[idx - i, 'B'] > 0:
                    df.loc[idx, 'A'] = df.loc[idx - i, 'A']
                    df.loc[idx, 'B'] = df.loc[idx - i, 'B']
                else:
                    i += 1
            except KeyError:
                df.loc[idx, 'A'] = 0
                df.loc[idx, 'B'] = 0


这是第二个问题的解决方案:

df2 = df[(df.A > 0)].A
    for idx in df2.index:
        if df.loc[idx + 1, 'A'] > 0:
            df.loc[idx, 'A'] = 0
    df2 = df[(df.B > 0)].B
    for idx in df2.index:
        if df.loc[idx + 1, 'B'] > 0:
            df.loc[idx, 'B'] = 0


现在做Pandas巫毒教,使它成为一个单一的行。

pftdvrlh

pftdvrlh1#

使用numpy,你可以做以下事情:

import numpy as np
def clossest_zero(arr, arr_idx, n):
    return np.maximum.reduceat((1 - arr) * n, np.r_[0, arr_idx])[:-1]

def compare_replace(arr1, arr2):
    A, B = np.array(arr1), np.array(arr2)
    n = np.arange(A.size)
    idx = np.where(A * B == 1)[0]
    idx2 = clossest_zero(A, idx, n) > clossest_zero(B, idx, n)
    A[idx[idx2]] = 0
    B[idx[~idx2]] = 0
    return A, B

compare_replace(np.array([0,1,1,1,0,0,1]), np.array([1,0,1,1,1,1,1]))
(array([0, 1, 1, 1, 0, 0, 0]), array([1, 0, 0, 0, 1, 1, 1]))

字符串
第二部分:

def replace_ones(x):
    x[:-1][(x[1:] * x[:-1]) == 1] = 0
    return x

replace_ones(np.array([1, 1, 0, 1, 0, 1, 1, 1]))
array([0, 1, 0, 1, 0, 0, 0, 1])

dgtucam1

dgtucam12#

我不确定使用numpy内置函数是否有更好的解决方案,但你肯定不需要子列表来解决这个问题。
下面是我的算法1:

def func1(arr1,arr2):
#part 1
for i in range(len(arr1)):
    if arr1[i] and arr2[i]:
        print(i)
        for j in range(i,-1,-1): #loop back to start
            if not arr1[j] and not arr2[j]:
                arr1[i],arr2[i] = 0,0
                break
            if not arr1[j]: 
                arr1[i] = 0
                break
            if not arr2[j]: 
                arr2[i] = 0
                break
    return arr1,arr2

字符串
总而言之,查看两个列表,比较数组之间的值,当你在同一个索引中发现两个1时,向后循环以找出要替换的。
您只需要比较每个算法的值对。
第二个算法非常简单,只需要向后循环,如果相邻的两个索引都包含1,就用0替换后者。

def func2(arr):
    for i in range(len(arr)-1,0,-1):
        if arr[i] and arr[i-1]:
            arr[i] = 0
    return arr


将func1然后func2应用于给定的示例数组后的输出:

arr1 = [0 1 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 1 0 0 1 0 0 0 0 0 0 0 0 0 1 0 0 1
 0 0 0 0 0 0 1 0 0 1 0 0 0 0 0 0 0 0 0 1 0 0 0 1 0 0 1 0 0 0 1 0 0 1 0 0 0
 1 0 0 0 0 0 0 1 0 0 1 0 1 0 0 0 0 0 0 1 0 0 0 0 1 0]
arr2 = [0 0 0 0 1 0 0 0 1 0 0 0 1 0 0 0 0 1 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0
 0 0 0 1 0 0 0 0 0 0 0 0 1 0 1 0 0 1 0 0 0 0 1 0 0 1 0 1 0 0 0 0 0 0 0 0 1
 0 0 0 0 1 0 0 0 0 0 0 1 0 0 1 0 0 0 0 0 0 0 0 1 0 0]

8iwquhpp

8iwquhpp3#

如果没有一个简单、可重复的示例(输入和所需的输出),很难解释您的条件。
歧义的一个来源是当你说:
(...)找出哪一个数组具有向后看的最接近的“0”,并将该数组中的“1”替换为“0”。
这是否意味着这个新插入的0现在可以用于将来确定“向后看最近的0”?如果是这样,则可能无法找到矢量化的解决方案。
另一方面,如果您认为输入是不可变的,并且希望根据输入中0的接近性将一些1更改为0来制作修改的副本,则您可能需要以下内容:

def zdist(a):
    cc = a.cumsum()
    return cc - np.maximum.accumulate(np.where(a == 0, cc, 0))

def f(a, b):
    a = a.copy()
    b = b.copy()
    p = a * b
    i = np.nonzero(p)[0]
    sel = np.where(zdist(a) <= zdist(b), 0, 1)
    a[i[sel[i] == 0]] = 0
    b[i[sel[i] == 1]] = 0
    return p, a, b

字符串
简单输入示例:

>>> f(
...     np.array([0,1,1,1,0,0,1]),
...     np.array([1,0,1,1,1,1,1]),
... )
(array([0, 0, 1, 1, 0, 0, 1]),
 array([0, 1, 1, 1, 0, 0, 0]),
 array([1, 0, 0, 0, 1, 1, 1]))


这是如何工作的?
第一部分zdist计算到任何1左侧最近的0的距离。例如:

>>> zdist(np.array([0,0,1,1,0,1,1,1,1,0]))
array([0, 0, 1, 2, 0, 1, 2, 3, 4, 0])


第二部分(函数f),p是乘积,并且只有在ab都是1的情况下才是1。那么,i是两个数组都是1的索引。而sel是一个选择器,它基于哪个数组具有最接近的0:(0: a1: b)的最大值。
结果是p, new_a, new_b的元组(原始的ab未被修改)。
对于第二个问题:

def g(a):
    return ((a == 1) & (np.r_[a[1:], 0] == 0)).astype(int)

>>> g(np.array([1, 1, 0, 1, 0, 1, 1, 1]))
array([0, 1, 0, 1, 0, 0, 0, 1])

yzxexxkh

yzxexxkh4#

尝试使用numpy方法为您的条件。我认为应该进一步寻找如何从后面找到索引为0

# if both have '1' in the same position
# if np.array_equal(arr1, arr2,): # If both have only 1 and 0
if np.array_equal(np.where(arr1 == 1)[0], np.where(arr2 == 1)[0]): # If they can have other integers compare using indices of 1s
    print("Yes ! Both have 1 in the same position")

    # Find the index of the target value when looking backward
    backward_index_1 = np.where(np.flipud(arr1) == 0)[0][0]
    backward_index_2 = np.where(np.flipud(arr2) == 0)[0][0]
    
    if backward_index_1 <= backward_index_2:
    print("Array 1 has the closest 0 in reverse order")
    # Replace "1" in that array with "0".
    arr1 = np.where(arr1 == 1, 0, arr1)
    else:
    print("Array 2 has the closest 0 in reverse order")
    # Replace "1" in that array with "0".
    arr2 = np.where(arr2 == 1, 0, arr2)
else:
    print("No ! Both don't have 1 in the same position")

字符串

相关问题