Вы можете создать список conditions
, а затем np.logical_and.reduce
:
x1 = df.x==1
y2 = df.y==2
z1 = df.z==1
y3 = df.y==3
m1 = np.logical_and.reduce([x1, y2, z1])
m2 = np.logical_and.reduce([x1, y3, z1])
Или concat
все маски вместе и проверить все True
s на строку по DataFrame.all
:
m1 = pd.concat([x1, y2, z1], axis=1).all(axis=1)
m2 = pd.concat([x1, y3, z1], axis=1).all(axis=1)
РЕДАКТИРОВАТЬ:
Если возможно, укажите имена столбцов со значениями для фильтрации в словаре:
d1 = {'x':1, 'y':2, 'z':1}
d2 = {'x':1, 'y':3, 'z':1}
m1 = np.logical_and.reduce([df[k] == v for k, v in d1.items()])
m2 = np.logical_and.reduce([df[k] == v for k, v in d2.items()])
Другой подход с merge
одной строкой DataFrame, созданный из словаря:
df1 = pd.DataFrame([d1]).merge(df)
РЕДАКТИРОВАТЬ:
Для общего решения можно проанализировать каждое значение файла для кортежей и использовать операторы :
df1 = pd.DataFrame({0: ['x==1', 'x==1'], 1: ['y==2', 'y<=3'], 2: ['z!=1', 'z>1']})
print (df1)
0 1 2
0 x==1 y==2 z!=1
1 x==1 y<=3 z>1
import operator, re
ops = {'>': operator.gt,
'<': operator.lt,
'>=': operator.ge,
'<=': operator.le,
'==': operator.eq,
'!=': operator.ne}
#if numeric, parse to float, else not touch ()e.g. if string
def try_num(x):
try:
return float(x)
except ValueError:
return x
L = df1.to_dict('r')
#https://stackoverflow.com/q/52620865/2901002
rgx = re.compile(r'([<>=!]+)')
parsed = [[rgx.split(v) for v in d.values()] for d in L]
L = [[(x, op, try_num(y)) for x,op,y in ps] for ps in parsed]
print (L)
[[('x', '==', 1.0), ('y', '==', 2.0), ('z', '!=', 1.0)],
[('x', '==', 1.0), ('y', '<=', 3.0), ('z', '>', 1.0)]]
А теперь фильтр по первому значению списка - первая строка файла:
m = np.logical_and.reduce([ops[j](df[i], k) for i, j, k in L[0]])
print (m)
[False False True False]