Pandas:将知识产权解析为国家/地区的最快方式

2024-02-27

我有一个函数find_country_from_connection_ip它需要一个 ip,经过一些处理后返回一个国家/地区。就像下面这样:

def find_country_from_connection_ip(ip):
    # Do some processing
    return county

我正在使用里面的功能apply方法。像下面这样:

df['Country'] = df.apply(lambda x: find_country_from_ip(x['IP']), axis=1)

因为它非常简单,所以我想要的是从 DataFrame 中的现有列评估新列,该列具有>400000 rows.

它运行,但速度非常慢,并抛出如下异常:

…………:设置复制警告: 尝试在 DataFrame 的切片副本上设置一个值。 尝试使用 .loc[row_indexer,col_indexer] = value 代替

请参阅文档中的警告:http://pandas.pydata.org/pandas-docs/stable/indexing.html#indexing-view-versus-copy http://pandas.pydata.org/pandas-docs/stable/indexing.html#indexing-view-versus-copy

if name == 'main': 在[38]中:

我明白这个问题,但不太清楚如何使用loc with apply and lambda.

注意:请建议您是否有更有效的替代解决方案,可以带来最终结果。

**** 编辑 ********

该函数主要是查找mmdb数据库如下:

def find_country_from_ip(ip):
    result = subprocess.Popen("mmdblookup --file GeoIP2-Country.mmdb --ip {} country names en".format(ip).split(" "), stdout=subprocess.PIPE).stdout.read()
    if result:
        return re.search(r'\"(.+?)\"', result).group(1) 
    else:
        final_output = subprocess.Popen("mmdblookup --file GeoIP2-Country.mmdb --ip {} registered_country names en".format(ip).split(" "), stdout=subprocess.PIPE).stdout.read()
        return re.search(r'\"(.+?)\"', final_output).group(1)

然而,这是一个代价高昂的操作,当你有一个带有以下内容的 DataFrame 时>400000行,应该需要时间。但多少钱呢?就是那个问题。大约需要2个小时,我想这也差不多了。


我会用maxminddb-geolite2(GeoLite) 模块。

首次安装maxminddb-geolite2 module

pip install maxminddb-geolite2

Python代码:

import pandas as pd
from geolite2 import geolite2

def get_country(ip):
    try:
        x = geo.get(ip)
    except ValueError:
        return pd.np.nan
    try:
        return x['country']['names']['en'] if x else pd.np.nan
    except KeyError:
        return pd.np.nan

geo = geolite2.reader()

# it took me quite some time to find a free and large enough list of IPs ;)
# IP's for testing: http://upd.emule-security.org/ipfilter.zip
x = pd.read_csv(r'D:\download\ipfilter.zip',
                usecols=[0], sep='\s*\-\s*',
                header=None, names=['ip'])

# get unique IPs
unique_ips = x['ip'].unique()
# make series out of it
unique_ips = pd.Series(unique_ips, index = unique_ips)
# map IP --> country
x['country'] = x['ip'].map(unique_ips.apply(get_country))

geolite2.close()

Output:

In [90]: x
Out[90]:
                     ip     country
0       000.000.000.000         NaN
1       001.002.004.000         NaN
2       001.002.008.000         NaN
3       001.009.096.105         NaN
4       001.009.102.251         NaN
5       001.009.106.186         NaN
6       001.016.000.000         NaN
7       001.055.241.140         NaN
8       001.093.021.147         NaN
9       001.179.136.040         NaN
10      001.179.138.224    Thailand
11      001.179.140.200    Thailand
12      001.179.146.052         NaN
13      001.179.147.002    Thailand
14      001.179.153.216    Thailand
15      001.179.164.124    Thailand
16      001.179.167.188    Thailand
17      001.186.188.000         NaN
18      001.202.096.052         NaN
19      001.204.179.141       China
20      002.051.000.165         NaN
21      002.056.000.000         NaN
22      002.095.041.202         NaN
23      002.135.237.106  Kazakhstan
24      002.135.237.250  Kazakhstan
...                 ...         ...

Timing:对于 171.884 个唯一 IP:

In [85]: %timeit unique_ips.apply(get_country)
1 loop, best of 3: 14.8 s per loop

In [86]: unique_ips.shape
Out[86]: (171884,)

结论:这将需要大约。在我的硬件上为您提供 400K 唯一 IP 的 DF 需要 35 秒:

In [93]: 400000/171884*15
Out[93]: 34.90726303786274
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Pandas:将知识产权解析为国家/地区的最快方式 的相关文章

随机推荐