You can apply a lambda on the df row-wise which checks whether the first character startswith 'K' and returns the last_valid_index which indexes that column on a row basis:
In [35]:
df['new_col'] = df.astype(str).apply(lambda x: x[x[x.str.startswith('K')].last_valid_index()], axis=1)
df
Out[35]:
fce1_1 fce1_2 fce2_1 fce2_2 new_col
0 K701 K712 K703 25 K703
1 Molly Molly K719 94 K719
2 Tina K709 Tina 57 K709
3 K876 Jape I841 62 K876
4 Amy Amy K987 70 K987
Breakdown of the above:
In [38]:
df.astype(str).apply(lambda x: x.str.startswith('K'), axis=1)
Out[38]:
fce1_1 fce1_2 fce2_1 fce2_2
0 True True True False
1 False False True False
2 False True False False
3 True False False False
4 False False True False
In [39]:
df.astype(str).apply(lambda x: x[x.str.startswith('K')].last_valid_index(), axis=1)
Out[39]:
0 fce2_1
1 fce2_1
2 fce1_2
3 fce1_1
4 fce2_1
dtype: object
EDIT
To handle no matches row-wise we can have a conditional condition inside the lambda:
In [67]:
data = {'fce1_1': [np.NaN, 'Molly', 'Tina', 'K876', 'Amy'],
'fce1_2': [np.NaN, 'Molly', 'K709', 'Jape', 'Amy'],
'fce2_1': [np.NaN, 'K719', 'Tina', 'I841', 'K987'],
'fce2_2': np.NaN}
df = pd.DataFrame(data)
df['new_col'] = df.astype(str).apply(lambda x: x[x.str.startswith('K')].last_valid_index() if x.str.startswith('K').any() else 'No Match', axis=1)
df
Out[67]:
fce1_1 fce1_2 fce2_1 fce2_2 new_col
0 NaN NaN NaN NaN No Match
1 Molly Molly K719 NaN fce2_1
2 Tina K709 Tina NaN fce1_2
3 K876 Jape I841 NaN fce1_1
4 Amy Amy K987 NaN fce2_1
that is closest to the column at the right?fce2_2will be prioritized over colfce2_1..etc