我有一个用户及其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
以及包含网络范围和对应的GeNAMID 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,并提取相应的地理名称并将其添加到
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个例子。事实上,
用户名
有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
这非常慢,因为dataframe/list上有嵌套循环。有没有一种更快的方法来利用numpy/pandas?或者至少有比上面的方法更快的方法?
有一个类似的问题(
How can I check if an ip is in a network in python 2.x?
),但1)不涉及熊猫/小熊猫,2)我想检查多个IP
多个网络
,和3)最高投票率的答案无法避免嵌套循环,这就是我缓慢的性能来源