【问题标题】:Pandas outer merge returning out of place values and extra NansPandas 外部合并返回不合适的值和额外的 Nans
【发布时间】:2018-01-17 12:18:02
【问题描述】:

我有两个数据框:fpmreal。请参阅以下示例:

          month   fpm          region_id
94934     11  3.106522e+07    5300108
94935     23  3.476453e+07    5300108
94936     35  4.480962e+07    5300108
94937     47  4.148533e+07    5300108
94938     59  4.324909e+07    5300108
94939     71  5.908792e+07    5300108
94940     83  6.218772e+07    5300108
94941     95  6.881312e+07    5300108

        region_id  month    gdp_region
72397    5300108     35  5.390220e+10
72398    5300108     47  5.845612e+10
72399    5300108     59  6.707650e+10
72400    5300108     71  7.573268e+10
72401    5300108     83  8.466141e+10
72402    5300108     95  9.340400e+10

我想通过region_idmonth合并它们。

为了做到这一点,我使用了命令:

j = pd.merge(real, fpm, how='outer', on=['region_id', 'month'], left_index='off', right_index='off')

发生的情况是,fpm 列中的一些外来值加入了region_id 5300108 的同一行,而实际的gdp_region 实际上并没有在正确的region_idmonth 处加入。

我检查过,两列都是同一类型:int

这是错误的结果。请注意,索引是不同的。我明确设置了index='off'

   region_id  month    gdp_region           fpm
72397    5300108     35  5.390220e+10  1.649367e+07
72398    5300108     47  5.845612e+10  1.968157e+07
72399    5300108     59  6.707650e+10  2.088269e+07
72400    5300108     71  7.573268e+10  4.027545e+06
72401    5300108     83  8.466141e+10  1.197713e+06
72402    5300108     95  9.340400e+10  1.383501e+06
72403    5300108    107  1.102996e+11  1.718117e+06
72404    5300108    119  1.243238e+11  1.827867e+06
72405    5300108    131  1.441741e+11  2.053814e+06
72406    5300108    143  1.545690e+11  2.597804e+06
72407    5300108    155  1.641013e+11  2.908494e+06
72408    5300108    167  1.759067e+11  3.394452e+06
72409    5300108    179  1.974321e+11  4.022392e+06
94934    5300108     11           NaN  3.106522e+07
94935    5300108     23           NaN  3.476453e+07
94936    5300108     35           NaN  4.480962e+07
94937    5300108     47           NaN  4.148533e+07
94938    5300108     59           NaN  4.324909e+07
94939    5300108     71           NaN  5.908792e+07
94940    5300108     83           NaN  6.218772e+07
94941    5300108     95           NaN  6.881312e+07

感谢任何建议。 谢谢。

【问题讨论】:

  • pd.merge(real, fpm, how='left', on=['region_id', 'month'])
  • 如果我使用 how='left' 会丢失例如第 11 个月的 'fpm' 信息。
  • 然后使用how='right'

标签: python pandas merge


【解决方案1】:

试试这样简单的,

j = real.merge(fpm, how = 'right', on = ['region_id', 'month'])

正如pandas document 提到的,“如果在列上连接列,DataFrame 索引将被忽略。否则,如果在索引或列上的索引上连接索引,则将传递索引”。

【讨论】:

  • 正如我所说(上面的评论),结果帧没有我没有 gdp_region 的 fpm 信息(例如,在第 11 个月)。因此,我丢失了信息。我想要一个尽可能完整的表,尽管 Nan 我的信息实际上从原始数据库中丢失了
  • @BFurtado 尝试how = 'outer',你会得到NaN 值,这就是你想要的输出。
  • 这正是我在示例中所做的。但是看到结果不正确。南人不错。但是同一月份和 region_id 的 fpm 值不同
  • @BFurtado 我是根据我的记忆做到的,如果是这种情况,您必须添加 left_index=True, right_index=True,如 pandas 文档引用中所述。我会更新答案。
  • 请重新更新答案,因为同时使用left_index=Trueright_index=True 会产生 OP 的问题。我只使用其中 1 个不会遇到麻烦,但这仍然会创建无意义的索引。 :)
【解决方案2】:

对于几乎对称的解决方案,无论您执行哪个合并,月份都以相同的顺序排列,您可以使用(几乎)等价的表达式:

j = fpm.merge(real, how = 'outer', on = ['region_id', 'month']).sort_values('month')

j2 = real.merge(fpm, how = 'outer', on = ['region_id', 'month']).sort_values('month')

j3 = pd.merge(real, fpm, how = 'outer', on = ['region_id', 'month']).sort_values('month')

请注意left_index='off'之类的不是pandas支持的。它使用布尔值,其默认值设置为 False,这正是您想要的行为。

它为我返回:

   month         fpm  region_id    gdp_region
0     11  31065220.0    5300108           NaN
1     23  34764530.0    5300108           NaN
2     35  44809620.0    5300108  5.390220e+10
3     47  41485330.0    5300108  5.845612e+10
4     59  43249090.0    5300108  6.707650e+10
5     71  59087920.0    5300108  7.573268e+10
6     83  62187720.0    5300108  8.466141e+10
7     95  68813120.0    5300108  9.340400e+10

如果这不是您的结果,那么可能在您的数据框中有一个名为“fpm”的额外列,名为“real”。但是,我可以通过设置 left_index=True, right_index=True 重新创建您的原始问题,所以我认为您使用“off”的关键字定义使 python 解释了布尔值 True 而不是所需的行为。

现在,使用left_index=True 将填补缺失的索引,因为数据长度与最后一个已知索引值不同:

j4 = pd.merge(fpm, real, how = 'outer', on = ['region_id', 'month'], left_index=True, right_index=False).sort_values('month')
           month         fpm  region_id    gdp_region
72402     11  31065220.0    5300108           NaN
72402     23  34764530.0    5300108           NaN
72397     35  44809620.0    5300108  5.390220e+10
72398     47  41485330.0    5300108  5.845612e+10
72399     59  43249090.0    5300108  6.707650e+10
72400     71  59087920.0    5300108  7.573268e+10
72401     83  62187720.0    5300108  8.466141e+10
72402     95  68813120.0    5300108  9.340400e+10

反之,索引被保留:

j5 = pd.merge(fpm, real, how = 'outer', on = ['region_id', 'month'], left_index=False, right_index=True).sort_values('month')
       month         fpm  region_id    gdp_region
94934     11  31065220.0    5300108           NaN
94935     23  34764530.0    5300108           NaN
94936     35  44809620.0    5300108  5.390220e+10
94937     47  41485330.0    5300108  5.845612e+10
94938     59  43249090.0    5300108  6.707650e+10
94939     71  59087920.0    5300108  7.573268e+10
94940     83  62187720.0    5300108  8.466141e+10
94941     95  68813120.0    5300108  9.340400e+10

将两者都用作True 只会使用所有索引值组合,最终会得到很多 NaN,或者如果您有实际数据,则填充该特定索引值的值组合:

j6 = pd.merge(fpm, real, how = 'outer', on = ['region_id', 'month'], left_index=True, right_index=True).sort_values('month')
       month         fpm  region_id    gdp_region
94934     11  31065220.0    5300108           NaN
94935     23  34764530.0    5300108           NaN
72397     35         NaN    5300108  5.390220e+10
94936     35  44809620.0    5300108           NaN
72398     47         NaN    5300108  5.845612e+10
94937     47  41485330.0    5300108           NaN
72399     59         NaN    5300108  6.707650e+10
94938     59  43249090.0    5300108           NaN
72400     71         NaN    5300108  7.573268e+10
94939     71  59087920.0    5300108           NaN
72401     83         NaN    5300108  8.466141e+10
94940     83  62187720.0    5300108           NaN
72402     95         NaN    5300108  9.340400e+10
94941     95  68813120.0    5300108           NaN

【讨论】:

    【解决方案3】:

    具有可重复输入的 sn-p 会很有帮助。您想要的输出也是如此。你可以先用left_index = False而不是'Off'试试这个:

    import pandas as pd
    
    fpm = pd.DataFrame({'idx':[94934,94935,94936,94937,94938,94939,94940,   94941],
                       'month': [11,23,35,47,59,71,83,95],
                       'fpm':   [3.106522e+07,3.476453e+07,4.480962e+07,    4.148533e+07,   4.324909e+07,   5.908792e+07,6.218772e+07,6.881312e+07],
                       'region_id':[5300108,5300108,5300108,5300108,5300108,5300108,5300108,5300108]})
    fpm = fpm.set_index(['idx'])
    
    real = pd.DataFrame({'idx':[72397,72398,72399,72400,72401,72402],
                       'region_id':[5300108,5300108,5300108,5300108,5300108,5300108],
                       'month':[35,47,59,71,83,95],
                        'gdp_region':[5.390220e+10,5.845612e+10,6.707650e+10,7.573268e+10,8.466141e+10,9.340400e+10]})
    
    real = real.set_index(['idx'])
    
    j = pd.merge(real, fpm, how='outer', on=['region_id', 'month'], left_index=False, right_index=False).sort_values(['region_id', 'month'])
    print(j)
    

    这是否代表您想要的输出?

    【讨论】:

    • 有趣的是,您的实现代表了所需的输出。但是,这不是我的实际数据发生的情况。我猜这意味着问题不在合并命令中,而是在 DataFrames 的数据中的某个地方?
    • 哇。去搞清楚。现在我做了d = reale = fpmf = pd.merge(d, e, how='outer', on=['region_id', 'month']),它成功了!谢谢。尽管我仍然不明白为什么它在没有一个好的答案中不起作用。一定是DataFrame生成的问题。也许吧。
    • 确实on上的变量类型必须匹配!这就是关键。
    • 很酷,你想出来了。
    • 是的,@vestland 但是,Python 第一次让我失望了。当我进行连续合并时,pandas 不断将我的int 带入float。无论如何,如果你测试int(1) == float(1),Python 会返回True。经验教训:在 Pandas 中始终使用字符串作为键!
    猜你喜欢
    • 1970-01-01
    • 2010-09-05
    • 1970-01-01
    • 2021-05-31
    • 2021-09-03
    • 1970-01-01
    • 2021-10-19
    • 2016-03-11
    • 1970-01-01
    相关资源
    最近更新 更多