首页 > 解决方案 > 合并/加入两个数据帧,一个带有 IP 地址,一个带有 IP 网络

问题描述

我有两个数据帧,一个包含 IP 地址(df_ip),一个包含 IP 网络(df_network)。
IP 和网络的类型为ipaddress.ip_addressand ipaddress.ip_network,这可以检查 IP 是否位于网络 ( ip in network) 中。

数据框如下所示:

df_ip:
    IP
0   10.10.10.10
1   10.10.20.10
2   10.10.20.20

df_network:
    NETWORK         NETWORK_NAME
0   10.10.10.0/28   Subnet1
1   10.10.20.0/27   Subnet2

我想与 合并/加入df_ipdf_network每行添加 IP 所在的网络的名称。
对于这个小实例,它应该返回以下内容:

df_merged:
    IP            NETWORK_NAME
0   10.10.10.10   Subnet1
1   10.10.20.10   Subnet2
2   10.10.20.20   Subnet2

我的实际数据帧要大得多,所以 id 更喜欢不使用 for 循环来保持效率。
我怎样才能最好地做到这一点?如果这需要更改数据类型,那没关系。

注意:为了方便起见,我在下面添加了代码来创建数据。

import pandas as pd
import ipaddress

# Create small IP DataFrame
values_ip = [ipaddress.ip_address('10.10.10.10'),
             ipaddress.ip_address('10.10.20.10'),
             ipaddress.ip_address('10.10.20.20')]

df_ip = pd.DataFrame()
df_ip['IP'] = values_ip

# Create small Network DataFrame
values_network = [ipaddress.ip_network('10.10.10.0/28'),
                  ipaddress.ip_network('10.10.20.0/27')]
names_network = ['Subnet1',
                 'Subnet2']

df_network = pd.DataFrame()
df_network['NETWORK'] = values_network
df_network['NETWORK_NAME'] = names_network

标签: pythonpandasdataframeip-address

解决方案


避免任何循环的一种有效方法是使用 numpy 数组来检查 where ip & netmask == network_address,这是如何检查 ip 是否位于网络内。

请注意,这仅返回第一个匹配的网络名称

import numpy as np
net_masks = df_network.NETWORK.apply(lambda x: int(x.netmask)).to_numpy()
network_addresses = df_network.NETWORK.apply(lambda x: int(x.network_address)).to_numpy()

def get_first_network(ip):
    is_in_network = int(ip) & net_masks == network_addresses
    indices = np.argwhere(is_in_network)
    if indices.size>0:
        return df_network.loc[int(indices[0]), 'NETWORK_NAME' ]
    else:
        None

df_ip['network_name'] = df_ip.IP.apply(get_first_network)

这导致:

            IP network_name
0  10.10.10.10      Subnet1
1  10.10.20.10      Subnet2
2  10.10.20.20      Subnet2

推荐阅读