Pandas relabel rows to recognize unique values within a groupby
<p>I have a <code>Pandas DataFrame</code> that describes some version testing and looks like this:</p>

<pre><code>MailingName  EmailSubject    MailingID
Promo_v1s1    Hello!          A8FEFE
Promo_v1s2    Line 2          A8FEFE
Promo_v2s1    Line 2          A8FEFE
Promo_v2s2    Yo!             A8FEFE
Promo_v2S3    Hello!          A8FEFE
deal_v2s1     Line 2          bbb
deal_v2s2     Yo!             bbb
deal_v2ss     Hello           bbb
</code></pre>

<p>The same mailing campaign, with different version tests, can be identified by the <code>MailingID</code> (so that would be the <code>groupby</code> term for more characteristics).</p>

<p>The naming convention for <code>MailingName</code> for these is that <code>v + a number</code> indicates the email body version that was tested, and <code>s + a number</code> indicates the email subject line that was tested in a particular combo. However, the convention is not helpful in the sense that the subject line from a <code>v1s1</code> is not necessarily the same as a subject line in <code>v2s2</code> even when the mailingID is shared. </p>

<p>I want to, within each <code>MailingID</code> group, have all email subject lines that are actually identical, have the same 'subject line version number'. So I'd like to create another column that would result in something like this:</p>

<pre><code> MailingName  EmailSubject    MailingID      TrueEmailVersionNumber
Promo_v1s1    Hello!          A8FEFE               1
Promo_v1s2    Line 2          A8FEFE               2
Promo_v2s1    Line 2          A8FEFE               2
Promo_v2s2    Yo!             A8FEFE               3
Promo_v2S3    Hello!          A8FEFE               1
deal_v2s1     Line 2          bbb                  1
deal_v2s2     Yo!             bbb                  2
deal_v2ss     Hello           bbb                  3
</code></pre>

<p>Basically I want to add unique labels, per group, to a column. How can I do this with <code>Pandas</code>?</p>

<p>I had an idea of getting a starting in a clunky way like so:</p>

<pre><code>def processThis(x):
    uni = list(set(x))
    keys = {x_i:uni.index(x_i) for x_i in x}
    return keys
ab_data.groupby('mailing_id')['subject'].apply(processThis)
</code></pre>

<p>But this actually did not yield back a list of dictionaries, so even my first step is a non-starter. Thanks for any advice!</p>

<pre><code>In [229]: df
Out[229]: 
  MailingName EmailSubject MailingID
0  Promo_v1s1       Hello!    A8FEFE
1  Promo_v1s2       Line 2    A8FEFE
2  Promo_v2s1       Line 2    A8FEFE
3  Promo_v2s2          Yo!    A8FEFE
4  Promo_v2S3       Hello!    A8FEFE
5   deal_v2s1       Line 2       bbb
6   deal_v2s2          Yo!       bbb
7   deal_v2ss        Hello       bbb

In [230]: def f(x):
     ...:     unq = list(x['EmailSubject'].unique())
     ...:     return pd.Series([unq.index(y) + 1 for y in x['EmailSubject']])
     ...: 

In [231]: df['TrueEmailVersionNumber'] = df.groupby('MailingID').apply(f).values

In [232]: df
Out[232]: 
  MailingName EmailSubject MailingID  TrueEmailVersionNumber
0  Promo_v1s1       Hello!    A8FEFE                       1
1  Promo_v1s2       Line 2    A8FEFE                       2
2  Promo_v2s1       Line 2    A8FEFE                       2
3  Promo_v2s2          Yo!    A8FEFE                       3
4  Promo_v2S3       Hello!    A8FEFE                       1
5   deal_v2s1       Line 2       bbb                       1
6   deal_v2s2          Yo!       bbb                       2
7   deal_v2ss        Hello       bbb                       3
</code></pre>

python pandas