假设我有以下 DataFrame:
>>>df = pd.DataFrame([[5,2,3,11],[5,3,3,8],[9,4,11,12],[5,14,15,16]],columns=["a","b","c","d"])
>>>df
a b c d
0 5 2 3 11
1 5 3 3 8
2 9 4 11 12
3 5 14 15 16
如果我想匹配具有列值的所有行:'a' 等于 5,'b' < 10 和 'c' 大于或等于 3,我可以执行以下操作:
df[(df['a'] == 5) & (df['b'] < 10) & (df['c'] >= 3)]
这会给我我想要的结果:
a b c d
0 5 2 3 11
1 5 3 3 8
输入该代码以匹配行很费力,所以我决定制作一个名为 row_matcher
的函数这将采用 2 个参数:一个 Pandas DataFrame 和一个长度为 3 的列表列表 - 选择列、运算符和值。
def get_operator_fn(op):
import operator
return {
'<' : operator.lt,
'<=' : operator.le,
'==' : operator.eq,
'!=' : operator.ne,
'>=' : operator.ge,
'>' : operator.gt,
'&' : operator.and_
}[op]
def row_matcher(df,parameters):
import pandas as pd
"""Parameter should be [column,operation,value]
Example: ['trial',"==",1]
"""
operations = [df[get_operator_fn(operation)(df[column],value)] for column,operation,value in parameters]
return reduce(lambda left,right: pd.merge(left,right,how='inner'), operations)
>>>row_matcher(df,[["a","==",5],["b","<",10],["c",">=",3]])
不幸的是,这段代码会为 return reduce(...)
抛出一个错误。线:
TypeError: Could not compare <type 'str'> type with Series
我尝试更换 return reduce(...)
符合:
df[reduce(operator.and_,operations)]
这仍然会导致错误:TypeError: unsupported operand type(s) for &: 'str' and 'str'
如有任何帮助,我将不胜感激。
最佳答案
我认为使用 query() 会简单很多方法。使用这个,你的初始示例可以写成:
df.query('a==5 & b<10 & c>=3')
老实说,如果您使用 query() 方法,我认为您不会从您的函数中获益太多,除非您从外部文件中读取大量条件。如果仍想编写 row_matcher
函数,只需使用字符串连接将您的列表列表组合为单个字符串,遵守 query() 语法。获得单个字符串后,将其传递给 query() 方法。
您可能需要安装 numexpr
模块才能使用 query() 方法。您可以通过向 query() 方法提供关键字参数 engine='python'
来解决这个问题。这可能比使用 numexpr
模块效率低,因此如果性能成为问题,安装该模块可能是值得的。
关于python - 将列和值与行匹配的函数 - DataFrame 的交集,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34773251/