angelwally angelwally - 24 days ago 8
Python Question

Dynamic comparison with pandas AND

I have a dictionary with each column as a key in a

dataframe
like:

dict = {"colA":1,"colB":1,"colC":1}


with colA, colB, colC the columns of my
dataframe
.

I would like to do something like:

df.loc[(df["colA"] < = dict["colA"]) & (df["colB"] < = dict["colB"]) & (df["colC"] < = dict["colC"])]


but dynamically (I don't know the length of the dict / number of columns)

Is there a way to do a
&
with dynamic number of arguments?

Answer

You can use:

from  functools import reduce

df = pd.DataFrame({'colA':[1,2,0],
                   'colB':[0,5,6],
                   'colC':[1,8,9]})

print (df)
   colA  colB  colC
0     1     0     1
1     2     5     8
2     0     6     9

d = {"colA":1,"colB":1,"colC":1}

a = df[(df["colA"] <= d["colA"]) & (df["colB"] <= d["colB"]) & (df["colC"] <= d["colC"])]
print (a)
   colA  colB  colC
0     1     0     1

Solution with creating Series, compare with le, check all True by all and last use boolean indexing:

d = {"colA":1,"colB":1,"colC":1}

s = pd.Series(d)
print (s)
colA    1
colB    1
colC    1
dtype: int64

print (df.le(s).all(axis=1))
0     True
1    False
2    False
dtype: bool

print (df[df.le(s).all(axis=1)])
   colA  colB  colC
0     1     0     1

Another solution with numpy.logical_and and reduce for creating mask and list comprehension for apply conditions:

print ([df[x] <= d[x] for x in df.columns])
[0     True
1    False
2     True
Name: colA, dtype: bool, 0     True
1    False
2    False
Name: colB, dtype: bool, 0     True
1    False
2    False
Name: colC, dtype: bool]

mask = reduce(np.logical_and, [df[x] <= d[x] for x in df.columns])
print (mask)
0     True
1    False
2    False
Name: colA, dtype: bool

print (df[mask])
   colA  colB  colC
0     1     0     1