say I have three numpy arrays:
a = np.array([8,2,10,10])
b = np.array([5,6,7,8])
c = np.array([9,10,11,12])
I would like to do an element-wise test if a is between b and c. And if so, return something like:
["Pass","Fail","Pass","Pass"]
say I have three numpy arrays:
a = np.array([8,2,10,10])
b = np.array([5,6,7,8])
c = np.array([9,10,11,12])
I would like to do an element-wise test if a is between b and c. And if so, return something like:
["Pass","Fail","Pass","Pass"]
For a pure numpy solution, you can use np.where():
np.where((b < a) & (a < c), 'Pass', 'Fail')
# array(['Pass', 'Fail', 'Pass', 'Pass'], dtype='<U5')
As noted in comments, additional checking is needed if you want either b<a<c or c<a<b:
bac = (b < a) & (a < c)
cab = (c < a) & (a < b)
np.where(bac | cab, 'Pass', 'Fail')
If a, b, and c are not numpy arrays themselves but instead columns of lists:
a = np.array([[8,2,3], 2, 10, 10], dtype=object)
b = np.array([[5,4,5], 6, 7, 8], dtype=object)
c = np.array([[9,6,7], 10, 11, 12], dtype=object)
df = pd.DataFrame({'a': a, 'b': b, 'c': c})
# a b c
# 0 [8, 2, 3] [5, 4, 5] [9, 6, 7]
# 1 2 6 10
# 2 10 7 11
# 3 10 8 12
Use applymap() to convert each cell to a numpy array and then apply() the betweenness test along axis=1:
def between(row):
bac = (row.b < row.a) & (row.a < row.c)
cab = (row.c < row.a) & (row.a < row.b)
return np.where(bac | cab, 'Pass', 'Fail')
df = df.applymap(np.array)
df.apply(between, axis=1)
# 0 [Pass, Fail, Fail]
# 1 Fail
# 2 Pass
# 3 Pass
# dtype: object
Via Pandas:
df=pd.DataFrame(data=[a,b,c]).T
df.columns=['a','b','c']
Finally:
result=df['a'].between(df['b'],df['c']).apply(lambda x:'Pass' if x else 'Fail').values
Now If you print result you will get your desired output:
array(['Pass', 'Fail', 'Pass', 'Pass'], dtype=object)
AS Noted in comment by @user2357112 supports Monica:
pandas.Series.between defaults to an inclusive "betweenness" check, so 2 is considered to be between 2 and 3. If you want an exclusive check, you can pass inclusive=False
i.e:
result=df['a'].between(df['b'],df['c'],inclusive=False).apply(lambda x:'Pass' if x else 'Fail').values
Note: It is not much efficient(speedwise) as compared to numpy's where() method for large/huge data but it will do the work