Merge/Join 两个数据帧,一个有 IP 地址,一个有 IP 网络
Merge/Join two Dataframes, one with IP addresses, one with IP Networks
我有两个数据帧,一个包含 IP 地址 (df_ip
),一个包含 IP 网络 (df_network
)。
IP 和网络的类型为 ipaddress.ip_address
和 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
我想 merge/join df_ip
和 df_network
,每行添加 IP 所在的网络名称。
对于这个小实例,它应该 return 以下内容:
df_merged:
IP NETWORK_NAME
0 10.10.10.10 Subnet1
1 10.10.20.10 Subnet2
2 10.10.20.20 Subnet2
我的实际数据帧要大得多,所以我宁愿不使用 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
避免任何循环的有效方法是使用 numpy 数组检查位置 ip & netmask == network_address
,这就是检查 ip 是否位于网络内的方法。
注意这returns只是第一个匹配的网络名称
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
我有两个数据帧,一个包含 IP 地址 (df_ip
),一个包含 IP 网络 (df_network
)。
IP 和网络的类型为 ipaddress.ip_address
和 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
我想 merge/join df_ip
和 df_network
,每行添加 IP 所在的网络名称。
对于这个小实例,它应该 return 以下内容:
df_merged:
IP NETWORK_NAME
0 10.10.10.10 Subnet1
1 10.10.20.10 Subnet2
2 10.10.20.20 Subnet2
我的实际数据帧要大得多,所以我宁愿不使用 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
避免任何循环的有效方法是使用 numpy 数组检查位置 ip & netmask == network_address
,这就是检查 ip 是否位于网络内的方法。
注意这returns只是第一个匹配的网络名称
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