我有一个(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.5
,994/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))
感谢您的帮助。
答案 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
这样,代码仍然可读性强,但是循环仅迭代匹配数,而不是行数。