У меня есть фрейм данных с идентификатором и некоторыми адресами электронной почты
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)
Одна идея:
#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 Он должен содержать электронные письма
Давайте попробуем проверить, чтобы символы после @
были либо 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]
о, хм. Я не могу получить результат. Что означает расплавленное['значение']?