Python 如何避免np中的NaN。两个数据帧之间的位置?

Python 如何避免np中的NaN。两个数据帧之间的位置?,python,pandas,numpy,Python,Pandas,Numpy,我有客户数据,想用返回“匹配”或“不匹配”的np.where检查他们的电子邮件是否存在于单独的df中 然而,其中一封客户电子邮件是NaN,第二封df中的一封电子邮件是NaN,因此这封邮件作为匹配返回。如您所见,已找到stack overflow先生的匹配项 customers = pd.DataFrame({'firstname':['stack','Bar Bar','Foo Bar','jim','john','mary','jim'], 'lastna

我有客户数据,想用返回“匹配”或“不匹配”的np.where检查他们的电子邮件是否存在于单独的df中

然而,其中一封客户电子邮件是NaN,第二封df中的一封电子邮件是NaN,因此这封邮件作为匹配返回。如您所见,已找到stack overflow先生的匹配项

customers = pd.DataFrame({'firstname':['stack','Bar Bar','Foo Bar','jim','john','mary','jim'],
                   'lastname':['overflow','Bar','Foo Bar','ryan','con','sullivan','Ryan'],
                   'email':[np.nan,'Bar','Foo Bar','jim@com','john@com','mary@com','Jim@com']})

customers

    firstname   lastname    email
0   jim             bob             NaN
1   Bar Bar     Bar     bar@com
2   Foo Bar     Foo Bar     foo@com
3   jim     ryan        jim@com
4   john        con     john@com
5   mary        sullivan    hello@com
6   jim     Ryan        jon@com
现在我想检查他们的电子邮件是否在另一个名为“电子邮件”的数据框中:


emails = pd.DataFrame({'emails':['mary@com','bar@com','foo@com','jim@com','john@com',np.nan,'jon@com']})

emails

    emails
0   mary@com
1   bar@com
2   foo@com
3   jim@com
4   john@com
5   NaN
6   jon@com

我将创建一个名为“check”的新列,该列将检查结果记录为“匹配”或“不匹配”


customers['check'] = np.where(customers['email'].isin(emails['emails']), 'match', 'no_match')

customers


    firstname   lastname    email       check
0   jim     bob     NaN     match
1   Bar Bar     Bar     bar@com     match
2   Foo Bar     Foo Bar     foo@com     match
3   jim     ryan        jim@com     match
4   john        con     john@com    match
5   mary        sullivan    hello@com   no_match
6   jim     Ryan        jon@com     match
除了吉姆·鲍勃的记录外,一切看起来都很好。他的电子邮件是NaN,在电子邮件数据框中有一个NaN。所以它作为匹配返回

最好的办法是什么

我正在考虑做一些激烈的事情,比如
fillna()
,然后将其更改为
'fakeNaN'
之类的字符串,这样就不会出现匹配。但一定有更好的办法

编辑:我刚刚尝试了以下方法:

定义了一个用于lambda的函数,如果客户没有电子邮件,则不返回任何电子邮件

def lam(r):

# if the email is nan, return no_email

    if r == np.nan:
        return 'no_email'

    elif r in emails['emails']:
        return 'match'

    elif not r in emails['emails']:
        return 'no_match'

# apply this lambda operation to the customer email row and return results to customer['check']

customers['check'] = customers.apply(lambda row: lam(row['email']), axis=1)

然而,它现在不会返回任何匹配项。有几场比赛

0    no_match
1    no_match
2    no_match
3    no_match
4    no_match
5    no_match
6    no_match
dtype: object
edit2:我现在注意到一些奇怪的事情

我可以查看
电子邮件['emails']
并查看
jim@com
是否有:

emails['emails']

0    mary@com
1     bar@com
2     foo@com
3     jim@com
4    john@com
5         NaN
6     jon@com
Name: emails, dtype: object
那么为什么这不起作用呢

'jim@com' in emails['emails']

False

isin
带有
np。选择

m1=customers.email.isin(emails.emails.dropna().values)
m2=customers.email.notna()
customers['check']=np.select([m1&m2,~m1&m2],['match','no match'],default='no_email')
customers
  firstname  lastname     email     check
0     stack  overflow       NaN  no_email        
1   Bar Bar       Bar       Bar  no match
2   Foo Bar   Foo Bar   Foo Bar  no match
3       jim      ryan   jim@com     match
4      john       con  john@com     match
5      mary  sullivan  mary@com     match
6       jim      Ryan   Jim@com  no match

isin
带有
np。选择

m1=customers.email.isin(emails.emails.dropna().values)
m2=customers.email.notna()
customers['check']=np.select([m1&m2,~m1&m2],['match','no match'],default='no_email')
customers
  firstname  lastname     email     check
0     stack  overflow       NaN  no_email        
1   Bar Bar       Bar       Bar  no match
2   Foo Bar   Foo Bar   Foo Bar  no match
3       jim      ryan   jim@com     match
4      john       con  john@com     match
5      mary  sullivan  mary@com     match
6       jim      Ryan   Jim@com  no match

将电子邮件另存为熊猫系列。有点非正统的方法

*1
用于将布尔值转换为整数

emails = pd.Series(['mary@com','bar@com','foo@com','jim@com','john@com',np.nan,'jon@com'])

(customers['email'].isin(emails)*1+customers['email'].isnull()*1).map({0:'No-Match',1:'Match',2:'No-Record'})

0   No-Record
1   No-Match
2   No-Match
3   Match
4   Match
5   Match
6   No-Match


将电子邮件另存为熊猫系列。有点非正统的方法

*1
用于将布尔值转换为整数

emails = pd.Series(['mary@com','bar@com','foo@com','jim@com','john@com',np.nan,'jon@com'])

(customers['email'].isin(emails)*1+customers['email'].isnull()*1).map({0:'No-Match',1:'Match',2:'No-Record'})

0   No-Record
1   No-Match
2   No-Match
3   Match
4   Match
5   Match
6   No-Match


不过,NaN仍在“匹配”。你看,这不是一场真正的比赛。也许可以检查我的编辑,看看我到底在用lambda函数做什么。不过NaN仍然是“匹配”的。你看,这不是一场真正的比赛。也许可以检查我的编辑,看看我想用lambda函数做什么。你是说
jim@com'在列表中(电子邮件['emails'])
<代码>电子邮件['emails']
是熊猫系列。
中的
不适用于该系列?我不知道。现在我知道了。就像字典一样,
中的
只会检查熊猫系列的键(索引)。所以在电子邮件中试试
1['emails']
你的意思是
'jim@com'在列表中(电子邮件['emails'])
<代码>电子邮件['emails']
是熊猫系列。
中的
不适用于该系列?我不知道。现在我知道了。就像字典一样,
中的
只会检查熊猫系列的键(索引)。因此,在电子邮件中尝试
1['emails']
这非常有效。但我必须同意温约本的答案,因为它更容易理解和解释。谢谢你的帮助和评论,如果我想重新访问lambda函数,你已经给了我一些想法。@SCool没问题。使用布尔函数创建数字类别有时可以节省大量时间。这非常有效。但我必须同意温约本的答案,因为它更容易理解和解释。谢谢你的帮助和评论,如果我想重新访问lambda函数,你已经给了我一些想法。@SCool没问题。使用布尔值创建数字类别有时可以节省大量时间。