Найдите строки, в которых значения в столбцах не соответствуют значениям из списка Python

У меня есть фрейм данных с идентификатором и некоторыми адресами электронной почты

personid  sup1_email      sup2_email         sup3_email        sup4_email
1         [email protected]  [email protected]      [email protected]    [email protected] 
5         [email protected]  [email protected]    [email protected]     nan
11        [email protected]   [email protected]  [email protected]    [email protected] 
52        [email protected]   [email protected]  [email protected]    [email protected]
65        [email protected]  [email protected]  [email protected]    [email protected]
89        [email protected]   [email protected]   [email protected]  [email protected]

Я хотел бы найти строки, которые не соответствуют списку допустимых значений электронной почты (т.е. НЕ "@abc.com", "@ABC.COM", "@Abc.com"). Я хотел бы получить это

personid  sup1_email      sup2_email         sup3_email        sup4_email
65        [email protected]  [email protected]  [email protected]    [email protected]
89        [email protected]   [email protected]   [email protected]  [email protected]

Я написал следующий код, и он работает, но мне приходится вручную проверять каждый столбец sup_email и повторять процесс, что неэффективно.

#list down all the variations of accepted email domains
email_adds = ['@abc.com','@ABC.COM','@Abc.com']
#combine the variations of email addresses in the list
accepted_emails = '|'.join(email_adds)


not_accepted = df.loc[~df['sup1_email'].str.contains(accepted_emails, na=False)]

Мне было интересно, есть ли более эффективный способ сделать это с помощью цикла for. До сих пор мне удавалось показывать столбец, содержащий непринятое электронное письмо, но не отображать строки, содержащие непринятые электронные письма. Ценю любую форму помощи, которую я могу получить, спасибо.

sup_emails = df[['sup1_email','sup2_email', 'sup3_email', 'sup4_email']]

#for each sup column, check if the accepted email addresses are not in it
for col in sup_emails:
    if any(x not in col for x in accepted_emails):
        print(col)
Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
3
0
1 181
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

Одна идея:

#list down all the variations of accepted email domains
email_adds = ['@abc.com','@ABC.COM','@Abc.com']
#combine the variations of email addresses in the list
accepted_emails = '|'.join(email_adds)

#columns for test
c = ['sup1_email','sup2_email', 'sup3_email', 'sup4_email']
#reshape and test all values, if `nan` pass `True`
m = df[c].stack(dropna=False).str.contains(accepted_emails, na=True).unstack().all(axis=1)

df = df[~m]
print (df)
   personid      sup1_email         sup2_email        sup3_email  \
4        65  [email protected]  [email protected]    [email protected]   
5        89   [email protected]   [email protected]  [email protected]   

           sup4_email  
4     [email protected]  
5  [email protected]  

Ваше решение с генератором и any:

c = ['sup1_email','sup2_email', 'sup3_email', 'sup4_email']

f = lambda y: any(x in y for x in email_adds) if isinstance(y, str) else True
df = df[~df[c].applymap(f).all(axis=1)]
print (df)
   personid      sup1_email         sup2_email        sup3_email  \
4        65  [email protected]  [email protected]    [email protected]   
5        89   [email protected]   [email protected]  [email protected]   

           sup4_email  
4     [email protected]  
5  [email protected]  

Вы можете сделать:

# list down all the variations of accepted email domains
email_adds = ['@abc.com','@ABC.COM','@Abc.com']

# combine the variations of email addresses in the list
accepted_emails = '|'.join(email_adds)

# create a single email column
melted = df.melt('personid')

# check the matching emails
mask = melted['value'].str.contains(accepted_emails, na=True)

# filter out the ones that do not match
mask = df['personid'].isin(melted.loc[~mask, 'personid'])

print(df[mask])

Выход

   personid      sup1_email  ...        sup3_email          sup4_email
4        65  [email protected]  ...    [email protected]     [email protected]
5        89   [email protected]  ...  [email protected]  [email protected]

[2 rows x 5 columns]

о, хм. Я не могу получить результат. Что означает расплавленное['значение']?

wjie08 18.12.2020 09:24

@ wjie08 Он должен содержать электронные письма

Dani Mesejo 18.12.2020 09:25
Ответ принят как подходящий

Давайте попробуем проверить, чтобы символы после @ были либо ABC, либо abc, либо Abc во всех столбцах. Конечно, нам может понадобиться временно отфильтровать PersonID. После проверки отмените результат с помощью ~ и замаскируйте их.

df[-(df.iloc[:,1:].apply(lambda x: x.str.contains('(\@(?=ABC|abc|Abc))').all(), axis=1))]



 personid      sup1_email         sup2_email        sup3_email  \
4      65.0  [email protected]  [email protected]    [email protected]   
5      89.0   [email protected]   [email protected]  [email protected]   

           sup4_email  
4     [email protected]  
5  [email protected]  

Другие вопросы по теме