pandas 将数据框与 NaN(或“未知”)合并以查找缺失值

Posted

技术标签:

【中文标题】pandas 将数据框与 NaN(或“未知”)合并以查找缺失值【英文标题】:pandas merge dataframe with NaN (or "unknown") for missing values 【发布时间】:2015-03-26 07:40:43 【问题描述】:

我有 2 个数据框,其中一个包含另一部分(但不是全部)行的补充信息。

names = df('names':['bob','frank','james','tim','ricardo','mike','mark','joan','joe'],
            'position':['dev','dev','dev','sys','sys','sys','sup','sup','sup'])
info = df('names':['joe','mark','tim','frank'],
           'classification':['thief','thief','good','thief'])

我想从上面的info 数据框中取出分类列,并将其添加到上面的names 数据框中。但是,当我执行combined = pd.merge(names, info) 时,生成的数据帧只有 4 行长。所有没有补充信息的行都会被删除。

理想情况下,我会将那些缺失列中的值设置为未知。导致数据框有些人是小偷,有些人很好,而其他人是未知的。

编辑: 我收到的第一个答案之一建议使用合并外部,这似乎做了一些奇怪的事情。这是一个代码示例:

names = df('names':['bob','frank','bob','bob','bob''james','tim','ricardo','mike','mark','joan','joe'],
            'position':['dev','dev','dev','dev','dev','dev''sys','sys','sys','sup','sup','sup'])
info = df('names':['joe','mark','tim','frank','joe','bill'],
           'classification':['thief','thief','good','thief','good','thief'])
what = pd.merge(names, info, how="outer")
what.fillna("unknown")

奇怪的是,在输出中我会得到一行结果名称是“bobjames”,而另一个位置是“devsys”。最后,即使账单没有出现在名称数据框中,它也会显示在结果数据框中。所以我真的需要一种方法来说明在这个其他数据框中查找一个值,如果你在这些列上发现了一些东西。

【问题讨论】:

【参考方案1】:

如果您仍在为此寻找答案:

您描述的“奇怪”的事情是由于您的代码中的一些小错误。例如,第一个(出现“bobjames”和“devsys”)是由于源数据帧中这两个值之间没有逗号。第二个是因为 pandas 不关心数据框的名称,而是在合并时关心列的名称(您有一个名为“名称”的数据框,但您的列也称为“名称”)。否则,合并似乎完全符合您的要求:

import pandas as pd
names = pd.DataFrame('names':['bob','frank','bob','bob','bob', 'james','tim','ricardo','mike','mark','joan','joe'], 
                      'position':['dev','dev','dev','dev','dev','dev', 'sys','sys','sys','sup','sup','sup'])

info = pd.DataFrame('names':['joe','mark','tim','frank','joe','bill'],
                     'classification':['thief','thief','good','thief','good','thief'])
what = pd.merge(names, info, how="outer")
what.fillna('unknown', inplace=True)

这将导致:

      names position classification
0       bob      dev        unknown
1       bob      dev        unknown
2       bob      dev        unknown
3       bob      dev        unknown
4     frank      dev          thief
5     james      dev        unknown
6       tim      sys           good
7   ricardo      sys        unknown
8      mike      sys        unknown
9      mark      sup          thief
10     joan      sup        unknown
11      joe      sup          thief
12      joe      sup           good
13     bill  unknown          thief

【讨论】:

【参考方案2】:

我认为你想执行 outer merge:

In [60]:

pd.merge(names, info, how='outer')
Out[60]:
     names position classification
0      bob      dev            NaN
1    frank      dev          thief
2    james      dev            NaN
3      tim      sys           good
4  ricardo      sys            NaN
5     mike      sys            NaN
6     mark      sup          thief
7     joan      sup            NaN
8      joe      sup          thief

有部分显示可以执行的合并类型:http://pandas.pydata.org/pandas-docs/stable/merging.html#database-style-dataframe-joining-merging

【讨论】:

谢谢你,但我仍然无法获得我想要的东西。我已经用更多上下文更新了我的问题。 为什么我们这里得到的是 NaN(浮点类型不是 Number)而不是 None?浮点类型进入纯字符串操作似乎很奇怪。 @MartinThøgersen 因为类型由于缺少值而被提升,对于标量值NA 有一些实验性支持:pandas.pydata.org/pandas-docs/stable/user_guide/… 但不适用于字符串,一旦混合了 dtypes 然后操作就变成了有问题,因为它变得模棱两可 如何将 classification 列中的 NaN 转换为 None? @MartinThøgersen 抱歉,我提出了一些我认为无需尝试就可以工作的东西,这是熊猫的怪癖,我查看了一个 git 问题:github.com/pandas-dev/pandas/issues/17494,这个工作:what['classification'].replace(np.NaN:None) 似乎@987654332 @ 只是被解释为 NaN,如果你传递一个 dict 那么它正确地达到了预期的结果,另外使用 where 也有效:what['classification'].where(pd.notnull(what['classification']) , 无), 相关***.com/questions/14162723/…【参考方案3】:

将其视为 SQL 连接操作。你需要一个left-outer 加入[1]。

names = pd.DataFrame('names':['bob','frank','james','tim','ricardo','mike','mark','joan','joe'],'position':['dev','dev','dev','sys','sys','sys','sup','sup','sup'])

info = pd.DataFrame('names':['joe','mark','tim','frank'],'classification':['thief','thief','good','thief'])

由于有names 而没有classification,所以left-outer 加入就可以完成这项工作。

a = pd.merge(names, info, how='left', on='names')

结果是……

>>> a
     names position classification
0      bob      dev            NaN
1    frank      dev          thief
2    james      dev            NaN
3      tim      sys           good
4  ricardo      sys            NaN
5     mike      sys            NaN
6     mark      sup          thief
7     joan      sup            NaN
8      joe      sup          thief

... 这很好。如果您查看这两个表,所有NaN 结果都可以。

干杯!

[1] - http://pandas.pydata.org/pandas-docs/stable/merging.html#database-style-dataframe-joining-merging

【讨论】:

【参考方案4】:

对于外连接或内连接,也可以使用join 函数。在上面的例子中,我们假设 names 是主表(该表中的所有行都必须出现在结果中)。然后运行左外连接使用:

what = names.set_index('names').join(info.set_index('names'), how='left')

分别

what = names.set_index('names').join(info.set_index('names'), how='left').fillna("unknown")

set_index 函数用于创建临时索引列(在两个表中相同)。当数据框包含此类索引列时,则不需要此步骤。例如:

# define index when create dataframes
names = pd.DataFrame('names':['bob',...],'position':['dev',...]).set_index('names')
info = pd.DataFrame('names':['joe',...],'classification':['thief',...]).set_index('names')

what = names.join(info, how='left')

要执行其他类型的连接,只需更改how 属性(允许left/right/inner/outer)。更多信息here

【讨论】:

以上是关于pandas 将数据框与 NaN(或“未知”)合并以查找缺失值的主要内容,如果未能解决你的问题,请参考以下文章

将大型 Dask 数据框与小型 Pandas 数据框合并

如何将两列数据框与 Nan 值结合起来? [复制]

Pandas:如何将两个不完整的数据帧合并或合并为一个完整的数据帧

将数据框与系列合并

Pandas 将多个数据帧与存储在多个列上的查找值合并

Pandas使用列标题作为值将多个列转换/合并为单个列