1

This is a follow up of the question of this I have a dataframe as below:

           KPI              Tata      JSW    scope   BIC    Peer   BIC_diff  Avg_diff
0        Gross Margin %    0.5820    0.4760   Max    0.582  0.268        0    0.313 
2          SG&A/Revenue    0.1410    0.0300   Min    0.029  0.0645     0.112  0.0765
3                   ROA    0.0640    0.0930   Max    0.093  0.0457    -0.029  0.0183
4                   ROE    0.1380    0.2430   Max    0.243  0.1024    -0.105  0.0356
5    Inventory Turnover    2.2000    3.2700   Min    1.71   3.892      0.49  -1.692
6        Current Ratio     0.9000    0.8000   Min    0.5    1.15        0.4  -0.25

Now I want to add another column whose cell value would be conditional of df['scope'], df['BIC_diff'] and df['Peer_diff']. So the resultant column looks like below. The underlying conditions are as follows:

cond_comments = [(df['scope']=='Max') & (df['BIC_diff'] > 0) & (df['Avg_diff'] > 0),
             (df['scope']=='Max') & (df['BIC_diff'] <= 0) & (df['Avg_diff'] <= 0),
             (df['scope']=='Max') & (df['BIC_diff'] <= 0) & (df['Avg_diff'] > 0),
             (df['scope']=='Min') & (df['BIC_diff'] > 0) & (df['Avg_diff'] > 0),
             (df['scope']=='Min') & (df['BIC_diff'] <= 0) & (df['Avg_diff'] <= 0),
             (df['scope']=='Min') & (df['BIC_diff'] > 0) & (df['Avg_diff'] <= 0)]

Based on the above conditions I am trying to add another column named comments as follows. Idea is to concatenate the KPI column text in the relevant position inside the comments along with values from BIC_diff and Peer_diff.

       KPI              BIC   Peer   BIC_diff  Avg_diff  comments
   Gross Margin %      0.582  0.268        0    0.313    Gross Margin is better than peer by 31.3% ## <-- `Gross Margin is from KPI. 31.3% is from Avg_diff.
     SG&A/Revenue      0.029  0.0645     0.112  0.0765   There is a scope of improvement for SG&A/Revenue by at least 7.65% ## <-- SG&A is taken from KPI. 7.65% is taken from Avg_diff.
              ROA      0.093  0.0457    -0.029  0.0183   There is a scope of improvement for ROA by 2.90% ## <-- ROA is from KPI. 2.90% is taken from BIC_diff absolute value. 
              ROE      0.243  0.1024    -0.105  0.0356   There is a scope of improvement for ROE by 10.50%
Inventory Turnover     1.71   3.892      0.49  -1.692
    Current Ratio      0.5    1.15        0.4  -0.25

In order to achieve the above, I have tried the following:

cond_comments = [(df['scope']=='Max') & (df['BIC_diff'] > 0) & (df['Avg_diff'] > 0),
             (df['scope']=='Max') & (df['BIC_diff'] <= 0) & (df['Avg_diff'] <= 0),
             (df['scope']=='Max') & (df['BIC_diff'] <= 0) & (df['Avg_diff'] > 0),
             (df['scope']=='Min') & (df['BIC_diff'] > 0) & (df['Avg_diff'] > 0),
             (df['scope']=='Min') & (df['BIC_diff'] <= 0) & (df['Avg_diff'] <= 0),
             (df['scope']=='Min') & (df['BIC_diff'] > 0) & (df['Avg_diff'] <= 0)]
vals_comments = ['{0} is better than BIC and peer by {1} and {2} respectively'.format(df['KPI'],df['BIC_diff'],df['Avg_diff']),
             '{0} has scope of improvement by atleast {1}'.format(df['KPI'],df['Avg_diff']),
             'While {0} is better than its peer, still there is a scope of improvement by {1}'.format(df['KPI'],df['BIC_diff']),
             '{0} has scope of improvement by atleast {1}'.format(df['KPI'],df['Avg_diff']),
             '{0} is better than BIC and peer by {1} and {2} respectively'.format(df['KPI'],df['BIC_diff'],df['Avg_diff']),
             'While {0} is better than its peer, still there is a scope of improvement by {1}'.format(df['KPI'],df['BIC_diff'])]
df['Comments'] = pd.np.select(cond_comments, vals_comments,default='No Comment')

However, the above code is not generating the comments as I have listed above.

Any help is appreciated.

P.S: please excuse for any possible bad formatting.

Community
  • 1
  • 1
pythondumb
  • 1,187
  • 1
  • 15
  • 30

1 Answers1

1

I would create a function that does all the conditionals first and then apply it row-wise. That way it is easier to add new conditions and see what condition leads to what result.

def create_comment(line: dict) -> str:
    # column values are accessible as in a dictionary
    if (line['scope']=='Max') and (line['BIC_diff'] > 0) and (line['Avg_diff'] > 0):
        return '{0} is better than BIC and peer by {1} and {2} respectively'.format(line['KPI'],line['BIC_diff'],line['Avg_diff'])
    elif (line['scope']=='Max') and (line['BIC_diff'] <= 0) and (line['Avg_diff'] <= 0):
        return '{0} has scope of improvement by at least {1}'.format(line['KPI'],line['Avg_diff'])
    ### Insert the remaining conditions below
    else:
        return 'No Comment'

# Then apply with axis=1 to do it row-wise
df['Comments'] = df.apply(create_comment, axis=1)
  • This was useful. Though I have made few modifications. Btw, I don't think we need the declaration `line:dict --> str` – pythondumb Oct 31 '19 at 09:22