【问题标题】:Fastest way to merge pandas dataframe on ranges在范围内合并熊猫数据框的最快方法
【发布时间】:2018-02-21 02:12:34
【问题描述】:

我有一个dataframe A

    ip_address
0   13
1   5
2   20
3   11
.. ........

还有一个dataframe B

    lowerbound_ip_address   upperbound_ip_address           country
0    0                       10                             Australia
1    11                      20                             China

基于此,我需要在A 中添加一列,以便

ip_address  country
13          China
5           Australia

我有一个想法,我应该编写一个函数,然后在 A 的每一行上调用 map。但是我将如何搜索 B 的每一行。有一个更好的方法吗。

【问题讨论】:

  • 是固定间隔10的上下界吗?
  • @ShreyasG 不,它们不是固定的

标签: python pandas numpy dataframe


【解决方案1】:

使用pd.IntervalIndex

In [2503]: s = pd.IntervalIndex.from_arrays(dfb.lowerbound_ip_address,
                                            dfb.upperbound_ip_address, 'both')

In [2504]: dfa.assign(country=dfb.set_index(s).loc[dfa.ip_address].country.values)
Out[2504]:
   ip_address    country
0          13      China
1           5  Australia
2          20      China
3          11      China

详情

In [2505]: s
Out[2505]:
IntervalIndex([[0, 10], [11, 20]]
              closed='both',
              dtype='interval[int64]')

In [2507]: dfb.set_index(s)
Out[2507]:
          lowerbound_ip_address  upperbound_ip_address    country
[0, 10]                       0                     10  Australia
[11, 20]                     11                     20      China

In [2506]: dfb.set_index(s).loc[dfa.ip_address]
Out[2506]:
          lowerbound_ip_address  upperbound_ip_address    country
[11, 20]                     11                     20      China
[0, 10]                       0                     10  Australia
[11, 20]                     11                     20      China
[11, 20]                     11                     20      China

设置

In [2508]: dfa
Out[2508]:
   ip_address
0          13
1           5
2          20
3          11

In [2509]: dfb
Out[2509]:
   lowerbound_ip_address  upperbound_ip_address    country
0                      0                     10  Australia
1                     11                     20      China

【讨论】:

  • 很好地使用了IntervalIndex;想在文档中添加一个像这样的小例子吗?
  • 如果dfa.ip_address 包含一个未被dfb 的任何索引边界覆盖的项目,您将如何处理可能发生的loc KeyError?
【解决方案2】:

IntervalIndex 从 pandas 0.20.0 开始,@JohnGalt 使用它的解决方案非常好。

在该版本之前,此解决方案可以按国家/地区扩展 IP 地址以实现完整范围。

df_ip = pd.concat([pd.DataFrame(
    {'ip_address': range(row['lowerbound_ip_address'], row['upperbound_ip_address'] + 1), 
     'country': row['country']}) 
    for _, row in dfb.iterrows()]).set_index('ip_address')
>>> dfa.set_index('ip_address').join(df_ip)
              country
ip_address           
13              China
5           Australia
20              China
11              China

【讨论】:

    【解决方案3】:

    试试pd.merge_asof

    df['lowerbound_ip_address']=df['ip_address']
    pd.merge_asof(df1,df,on='lowerbound_ip_address',direction ='forward',allow_exact_matches =False)
    Out[811]: 
       lowerbound_ip_address  upperbound_ip_address    country  ip_address
    0                      0                     10  Australia           5
    1                     11                     20      China          13
    

    【讨论】:

      猜你喜欢
      • 2013-10-23
      • 2015-12-28
      • 1970-01-01
      • 2017-09-04
      • 2017-11-06
      • 2012-07-06
      • 1970-01-01
      相关资源
      最近更新 更多