Я пытаюсь применить функцию очистки электронной почты к столбцу и записать результат в отдельный столбец.

Я не совсем уверен, как применить функцию к двум столбцам с .apply(), но вот что я пробовал:

Сначала настройте фрейм данных и словарь распространенных ошибок электронной почты:

import pandas as pd

df = pd.DataFrame({'emails':['jim@gmailcom','bob@gmail.com','mary@gmaicom','bobby@gmail.com'],
                   'result':['','','','']})

df

    emails          result
0   jim@gmailcom    
1   bob@gmail.com   
2   mary@gmaicom    
3   bobby@gmail.com 

# common mistakes:

correct_domain = {'gmailcom': 'gmail.com',
 'gmaicom': 'gmail.com',
 'gmaillom': 'gmail.com',
 'gmalcom': 'gmail.com'}

Теперь я хочу просмотреть электронную почту и заменить неправильно введенный домен на правильный. Например. gmailcom -> gmail.com

def clean_emails(x):

    # for each domain(key) in this dict ( e.g. 'gmailcom':'gmail.com')
    for mistake in correct_domain:  

        # if incorrect domain ('gmailcom') is in the email we're checking
        if mistake  in x['emails']:

            # replace it with the dict value which is the correctly formatted domain ('gmail.com')
            x['emails'] = x['emails'].replace(mistake ,correct_domain[mistake ])

            # record result
            x['result'] = 'email cleaned'

        else:
            x['result'] = 'no cleaning needed'

И тогда я получаю None, когда я применяю эту функцию:

df.apply(clean_emails,axis=1)

0    None
1    None
2    None
3    None
dtype: object

Я попытался использовать return в миксе, но не смог выяснить два отдельных результата для отдельных столбцов.

Мой желаемый результат, письма были очищены, а результат записан в result:

    emails          result
0   jim@gmail.com    'email cleaned'    
1   bob@gmail.com   'no cleaning needed'    
2   mary@gmail.com    'email cleaned'   
3   bobby@gmail.com 'no cleaning needed'

edit: Я думал, что добавление return x в конец функции вернет вновь отредактированные строки, но электронные письма не были очищены.

    emails  result
0   jim@gmail.com   email cleaned
1   bob@gmail.com   no cleaning needed
2   mary@gmaicom    no cleaning needed
3   bobby@gmail.com no cleaning needed
1
SCool 9 Июл 2019 в 12:10

3 ответа

Лучший ответ

Используйте Series.str.contains для проверки необходимости очистки с помощью numpy.where для столбца по условию, а затем используйте Series.str.replace с обратным вызовом для замены в словаре только необходимых строк:

pat = '|'.join(correct_domain.keys())
m = df['emails'].str.contains(pat, na=False)
df['result'] = np.where(m, 'email cleaned', 'no cleaning needed')
df.loc[m, 'emails'] = (df.loc[m, 'emails']
                         .str.replace(pat, lambda x: correct_domain[x.group()], regex=True))

print (df)
            emails              result
0    jim@gmail.com       email cleaned
1    bob@gmail.com  no cleaning needed
2   mary@gmail.com       email cleaned
3  bobby@gmail.com  no cleaning needed
1
jezrael 9 Июл 2019 в 10:14

Почему не двухслойный

df['result'] = df['emails'].str.contains('|'.join(correct_domain.keys()).map({0:'email cleaned', 1:'no cleaning needed'})
df['emails'] = df['emails'].str.replace('|'.join(correct_domain.keys()),list(correct_domain.values())[0])

И сейчас:

print(df)

Будет:

            emails              result
0    jim@gmail.com       email cleaned
1    bob@gmail.com  no cleaning needed
2   mary@gmail.com       email cleaned
3  bobby@gmail.com  no cleaning needed
1
U10-Forward 9 Июл 2019 в 09:16

Я думал, я вижу, у вас уже есть много предложений. Следуя вашей логике, мы можем получить вот так:


    df = pd.DataFrame({'emails':['jim@gmailcom','bob@gmail.com','mary@gmaicom','bobby@gmail.com']})

    regexExp = [r'gmailcom$', r'gmaicom$', r'gmaillom', r'gmalcom']

    df2 = df.replace(regex=regexExp, value='gmail.com')

    result = []
    for dfLines, df2Lines in zip(df.itertuples(),df2.itertuples()):
        if df2Lines.emails != dfLines.emails:
            result.append('email cleaned')
        else:
            result.append('no cleaning needed')

    df2['result'] = result

    print(df2)

0
Jerome 9 Июл 2019 в 09:56