【问题标题】:pandas merge dataframe with NaN (or "unknown") for missing valuespandas 将数据框与 NaN(或“未知”)合并以查找缺失值
【发布时间】: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”。最后,即使账单没有出现在名称数据框中,它也会显示在结果数据框中。所以我真的需要一种方法来说明在这个其他数据框中查找一个值,如果你在这些列上发现了一些东西。

【问题讨论】:

    标签: python pandas dataframe


    【解决方案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']) , 无), 相关stackoverflow.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

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2014-07-19
          • 2022-11-03
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2021-12-14
          相关资源
          最近更新 更多