Given, two Series bees
and knees
, if the ith value of bees
is NaN, double the ith value inside knees
.
import numpy as np
import pandas as pd
bees = pd.Series([True, True, False, np.nan, True, False, True, np.nan])
knees = pd.Series([5,2,9,1,3,10,5,2], index = [7,0,2,6,3,5,1,4])
print(bees)
# 0 True
# 1 True
# 2 False
# {==3 NaN==}
# 4 True
# 5 False
# 6 True
# {==7 NaN==}
# dtype: object
print(knees)
# 7 5
# 0 2
# 2 9
# {==6 1==} <-- double this
# 3 3
# 5 10
# 1 5
# {==4 2==} <-- double this
# dtype: int64
Expected Result
print(knees)
# 7 5
# 0 2
# 2 9
# {==6 2==}
# 3 3
# 5 10
# 1 5
# {==4 4==}
# dtype: int64
Solution¶
knees.loc[pd.isna(bees).to_numpy()] *= 2
print(knees)
# 7 5
# 0 2
# 2 9
# {==6 2==}
# 3 3
# 5 10
# 1 5
# {==4 4==}
# dtype: int64
Explanation
-
Identify which elements of
bees
areNaN
withpd.isna()
.pd.isna(bees) # 0 False # 1 False # 2 False # {==3 True==} # 4 False # 5 False # 6 False # {==7 True==} # dtype: bool
This results in a boolean Series.
-
Suppose we use this boolean Series to index
knees
..knees.loc[pd.isna(bees)] # 7 5 # 3 3 # dtype: int64
The elements it selects are not the ones we want.
knees.loc[pd.isna(bees)]
selects the elements ofknees
whose index matches those ofpd.isna(bees)
with True values.knees.loc[pd.isna(bees)] # pd.isna(bees) knees # 0 False ┌------{==7-----5==} # 1 False | 0 2 # 2 False | 2 9 # {==3-------True==}--┼--┐ 6 1 # 4 False | └---{==3-----3==} # 5 False | 5 10 # 6 False | 1 5 # {==7-------True==}--┘ 4 2
In other words,
pd.isna(bees)
has True values at indexes 3 and 7, soknees.loc[pd.isna(bees)]
selects rows ofknees
with index 3 and 7.However, the problem asked us to double the ith value of
knees
if the ith value ofbees
wasNaN
. The fourth and eighth elements ofbees
areNaN
, so we want to select the fourth and eight elements ofknees
. (Note thatknees
's index is not in sequential order.)To prevent Pandas from using the index of
pd.isna(bees)
to select elements ofknees
, we can remove the index by converting the boolean Series to a NumPy array. Then Pandas will select elements by the position of True values.knees.loc[pd.isna(bees).to_numpy()] # pd.isna(bees).to_numpy()] knees # False 7 5 # False 0 2 # False 2 9 # {==True==}-------------------------{==6-----1==} # False 3 3 # False 5 10 # False 1 5 # {==True==}-------------------------{==4-----2==} # <result> # 6 1 # 4 2 # dtype: int64
-
Double the value of those elements.
Easy enough, thanks to the
+=
operator :fontawesome-regular-face-smile:knees.loc[pd.isna(bees).to_numpy()] *= 2 print(knees) # 7 5 # 0 2 # 2 9 # {==6 2==} # 3 3 # 5 10 # 1 5 # {==4 4==} # dtype: int64