Pandas检查哪个子网IP地址属于
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Pandas检查哪个子网IP地址属于相关的知识,希望对你有一定的参考价值。
我有一个用户及其IP地址的pandas数据帧:
users_df = pd.DataFrame({'id': [1,2,3],
'ip': ['96.255.18.236','105.49.228.135','104.236.210.234']})
id ip
0 1 96.255.18.236
1 2 105.49.228.135
2 3 104.236.210.234
以及包含网络范围和相应地理标识ID的单独数据框:
geonames_df = pd.DataFrame({'network': ['96.255.18.0/24','105.49.224.0/19','104.236.128.0/17'],
'geoname': ['4360369.0','192950.0','5391959.0']})
geoname network
0 4360369.0 96.255.18.0/24
1 192950.0 105.49.224.0/19
2 5391959.0 104.236.128.0/17
对于每个用户,我需要检查他们的ip对所有网络,并拉出相应的geoname并将其添加到users_df
。我希望这个输出:
id ip geonames
0 1 96.255.18.236 4360369.0
1 2 105.49.228.135 192950.0
2 3 104.236.210.234 5391959.0
在这个例子中它很容易,因为它们是正确排序的,只有3个例子。实际上,users_df
有4000行,而geonames_df
有超过300万行
我目前正在使用这个:
import ipaddress
networks = []
for n in geonames_df['network']:
networks.append(ipaddress.ip_network(n))
geonames = []
for idx, row in users_df.iterrows():
ip_address = ipaddress.IPv4Address(row['ip'])
for block in networks:
if ip_address in block:
geonames.append(str(geonames_df.loc[geonames_df['network'] == str(block), 'geoname'].item()))
break
users_df['geonames'] = geonames
由于数据框/列表上的嵌套循环,这非常慢。是否有更快的方式来利用numpy / pandas?或者至少某种方式比上述方法更快?
这是一个类似的问题(How can I check if an ip is in a network in python 2.x?),但1)它不涉及pandas / numpy,2)我想检查多个IP对多个网络,3)最高投票的答案不能避免嵌套循环,这是我的慢表现源于
答案
我不认为可以避免嵌套循环,但我已将评论中提到的先前解决方案与pandas结合起来。你可以检查它是否更快。
import socket,struct
def makeMask(n):
"return a mask of n bits as a long integer"
return (2<<n-1) - 1
def dottedQuadToNum(ip):
"convert decimal dotted quad string to long integer"
return struct.unpack('L',socket.inet_aton(ip))[0]
def networkMask(network):
"Convert a network address to a long integer"
return dottedQuadToNum(network.split('/')[0]) & makeMask(int(network.split('/')[1]))
def whichNetwork(ip):
"return the network to which the ip belongs"
numIp = dottedQuadToNum(ip)
for index,aRow in geonames_df.iterrows():
if (numIp & aRow["Net"] == aRow["Net"]):
return aRow["geoname"]
return "Not Found"
geonames_df["Net"] = geonames_df["network"].map(networkMask)
users_df["geonames"] = users_df["ip"].map(whichNetwork)
以上是关于Pandas检查哪个子网IP地址属于的主要内容,如果未能解决你的问题,请参考以下文章