Python: pandas dynamically fill in values in string in each row using parameters

Viewed 135

This question has reference to this SO thread. For the sake of newness, I am providing the dataframe again.

ID         Static_Text                                           Params
1      Today, {0} is quite Sunny. Tomorrow, {1}              1-10-2020  
       may be little {2}
1      Today, {0} is quite Sunny. Tomorrow, {1}              2-10-2020
       may be little {2}
1      Today, {0} is quite Sunny. Tomorrow, {1}              Cloudy
       may be little {2}
2      Let's have a coffee break near {0}, if I              Balcony
       don't get any SO reply by {1}
2      Let's have a coffee break near {0}, if I              30
       don't get any SO reply by {1} mins

And this is what I want as a final Dataframe:

ID                     Final Text                 
1         Today, 1-10-2020 is quite Sunny. Tomorrow, 2-10-2020            
          may be little Cloudy
2         Let's have a coffee break near Balcony, if I              
          don't get any SO reply by 30 mins

One of the approach I am following is as follows:

df = df.groupby(['ID','Static_text']).['Params'].agg(list).reset_index()
df['Final Text'] = df.apply(lambda x : x['Static text'].format(','.join(x['Params'])),axis=1)

But the above method is throwing the following error:

IndexError: tuple index out of range

What I am missing here? I have figured out that some tricks need to be there in lambda x: part mayby. For a sake of simplicity, lets assume that we have all the dates in string.

1 Answers

For me working add * to string before joined values, used solution from this:

Also there is removed join.

Your error should be there is some number values around {} in Static_Text which not match by list after aggregate list - it means e.g. there are only 2 rows for ID=1 and there is {2} - so not exist 3th value in list and solution failed.

df = df.groupby(['ID','Static_Text'])['Params'].agg(list).reset_index()

df['Final Text'] = df.apply(lambda x : x['Static_Text'].format(*x['Params']),axis=1)

print (df)
   ID                                        Static_Text  \
0   1  Today, {0} is quite Sunny. Tomorrow, {1} may b...   
1   2  Let's have a coffee break near {0}, if I don't...   

                           Params  \
0  [1-10-2020, 2-10-2020, Cloudy]   
1                   [Balcony, 30]   

                                          Final Text  
0  Today, 1-10-2020 is quite Sunny. Tomorrow, 2-1...  
1  Let's have a coffee break near Balcony, if I d...  

Test:

print (df)
   ID                                        Static_Text     Params
0   1  Today, {0} is quite Sunny. Tomorrow, {1} may b...  1-10-2020
1   1  Today, {0} is quite Sunny. Tomorrow, {1} may b...  2-10-2020
2   2  Let's have a coffee break near {0}, if I don't...    Balcony
3   2  Let's have a coffee break near {0}, if I don't...         30


df = df.groupby(['ID','Static_Text'])['Params'].agg(list).reset_index()

df['Final Text'] = df.apply(lambda x : x['Static_Text'].format(*x['Params']),axis=1)
print (df)

IndexError: Replacement index 2 out of range for positional args tuple

You can find all rows with no match:

s1 = df['Static_Text'].str.extractall('{(\d+)}')[0].astype(int).max(level=0).add(1)
s2 = df.groupby(['ID','Static_Text'])['Params'].transform('size')
                                                          

df = df[s1.gt(s2)]
print (df)
   ID                                        Static_Text     Params
0   1  Today, {0} is quite Sunny. Tomorrow, {1} may b...  1-10-2020
1   1  Today, {0} is quite Sunny. Tomorrow, {1} may b...  2-10-2020
Related