Numpy结构化数组查询的简化写法及Pandas替代方案的可读性问询
Numpy结构化数组查询的简化写法及Pandas替代方案的可读性问询
嘿,我来帮你捋捋这个问题~
首先看你现有的Numpy代码,其实第一步的np.where完全是多余的——Numpy的布尔索引本身就可以直接筛选数组,不用绕去生成索引再取值。咱们可以先把这部分简化:
import numpy as np a = np.array([('Rex', 9, 18), ('Fido', 3, 22), ('Fido', 7, 42), ('Fluffy', 1, 30), ('Fido', 5, 19)], dtype=[('name', 'U10'), ('age', 'f4'), ('weight', 'f4')]) # 直接用布尔索引筛选,去掉不必要的np.where fido_filtered = a[(a['name'] == 'Fido') & (a['weight'] < 30)] oldestFidoUnder30 = fido_filtered[np.argmax(fido_filtered['age'])]
如果想再紧凑一点,甚至可以把两步合并成一行(不过可读性会稍微打折扣,看个人习惯):
oldestFidoUnder30 = a[(a['name'] == 'Fido') & (a['weight'] < 30)][np.argmax(a[(a['name'] == 'Fido') & (a['weight'] < 30)]['age'])]
但我更推荐分开写,毕竟代码可读性优先嘛。
再说说用Pandas这类数据框库的情况——绝对会更简洁、可读性更强,尤其是对于这种类似SQL的查询场景。Pandas的API设计非常贴近自然语言逻辑,咱们来看看实现:
import numpy as np import pandas as pd a = np.array([('Rex', 9, 18), ('Fido', 3, 22), ('Fido', 7, 42), ('Fluffy', 1, 30), ('Fido', 5, 19)], dtype=[('name', 'U10'), ('age', 'f4'), ('weight', 'f4')]) # 转成Pandas DataFrame df = pd.DataFrame(a) # 写法1:布尔索引 + nlargest oldest_fido = df[(df['name'] == 'Fido') & (df['weight'] < 30)].nlargest(1, 'age').iloc[0] # 写法2:用query方法,更像自然语言 oldest_fido = df.query("name == 'Fido' and weight < 30").nlargest(1, 'age').iloc[0]
你看,这两种写法几乎就是把你的需求“找叫Fido、体重小于30的最老狗狗”直接翻译成了代码,哪怕是不熟悉Numpy的人也能一眼看懂逻辑。如果后续还要做更复杂的查询(比如分组统计、多条件嵌套),Pandas的优势会更明显,代码的维护成本低很多。
备注:内容来源于stack exchange,提问作者Paul Jurczak
相关产品推荐
相关产品推荐

