numpy数组使用if语句删除重复项

时间:2020-08-14 11:45:33

标签: python arrays python-3.x list numpy

我有一个(112,7)形状的NumPy字符串数组。前几个元素只是字母,其余的是数字,如下所示

List[0] = array(['ID32', 'TRED', 'PLUS', '434','0.34', '11.9', '4.8'], dtype='<U14')
List[1] = array(['ID32', 'TRED', 'PLUS', '994','0.84', '44.3', '1.11'], dtype='<U14')
List[2] = array(['ID32', 'PROP', 'MINUS', '234','0.56', '44.3', '1.11'], dtype='<U14')

....

我想实现的是IF语句检查前三个元素,如果它们相同,则计算第四和第五个元素的比率,并从列表中删除较小的元素

例如,List[0]List[1]的前三个元素相同,因此请检查比率(434/0.34 = 1276.5994/0.84 = 1183),因此List[1]较小,应为从列表中删除。

这是我失败的尝试

for i, val in enumerate(List):
    if val[i][0] == val[i][1]
        print(val[3].astype(np.float)/val[4].astype(np.float))

感谢您的帮助。

2 个答案:

答案 0 :(得分:3)

如果您愿意使用pandas

import pandas as pd


# setup
l = [['ID32', 'TRED', 'PLUS', '434', '0.34', '11.9', '4.8'],
     ['ID32', 'TRED', 'PLUS', '994', '0.84', '44.3', '1.11'],
     ['ID32', 'PROP', 'MINUS', '234', '0.56', '44.3', '1.11']]

df = pd.DataFrame(l)

print (df.assign(ratio=df[3].astype(float)/df[4].astype(float))
         .sort_values([0,1,2,"ratio"], ascending=False)
         .drop_duplicates([0,1,2], keep="first")
         .sort_index()
         .drop("ratio", 1)
         .to_numpy())

结果:

[['ID32' 'TRED' 'PLUS' '434' '0.34' '11.9' '4.8']
 ['ID32' 'PROP' 'MINUS' '234' '0.56' '44.3' '1.11']]

答案 1 :(得分:0)

首先制作一个掩码以跟踪要保留的行,然后转换数字列:

keep = np.ones(len(arr), bool) # [True, True, True]
numer = arr[:,3].astype(float)
denom = arr[:,4].astype(float)

然后循环编辑我们要保留的行的掩码:

for ii in range(1, len(arr)): 
    if np.all(arr[ii-1,:3] == arr[ii,:3]): 
        if numer[ii-1] / denom[ii-1] < numer[ii] / denom[ii]: 
            keep[ii-i] = False 
        else: 
            keep[ii] = False 

现在,您将keep设为array([ True, False, True]),可以轻松地使用它来获得最终结果:

arr[keep]

给你

array([['ID32', 'TRED', 'PLUS', '434', '0.34', '11.9', '4.8'],
       ['ID32', 'PROP', 'MINUS', '234', '0.56', '44.3', '1.11']],
      dtype='<U14')

如果匹配的字符串数少于总行数,则可能更快:

matches = 1 + np.where((xxx[1:] == xxx[:-1]).all(1))[0] # [1]
for ii in matches: # now we already know the strings match
    if numer[ii-1] / denom[ii-1] < numer[ii] / denom[ii]: 
        keep[ii-i] = False 
    else: 
        keep[ii] = False 

这样,代码仍然可读性强,但是循环仅迭代匹配数,而不是行数。