Ahs*_*que 5 python geo dataframe pandas
我有一个find_country_from_connection_ip带ip 的函数,经过一些处理后返回了一个国家。如下所示:
def find_country_from_connection_ip(ip):
# Do some processing
return county
Run Code Online (Sandbox Code Playgroud)
我正在使用函数内部apply方法。如下所示:
df['Country'] = df.apply(lambda x: find_country_from_ip(x['IP']), axis=1)
Run Code Online (Sandbox Code Playgroud)
因为很简单,我想要的是从具有>400000行的DataFrame中的现有列中评估一个新列。
它运行,但是非常慢,并引发如下异常:
...........:SettingWithCopyWarning:试图在DataFrame的切片副本上设置一个值。尝试改用.loc [row_indexer,col_indexer] = value
请参阅文档中的警告:http : //pandas.pydata.org/pandas-docs/stable/indexing.html#indexing-view-versus-copy
如果name ==' main ':在[38]中:
我了解问题所在,但还不太清楚如何loc与applyand 结合使用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)
Run Code Online (Sandbox Code Playgroud)
但是,这是一项昂贵的操作,并且当您有一个带>400000行的DataFrame时,应该花费一些时间。但是多少钱?就是那个问题。我大约需要2个小时。
我会为此使用maxminddb-geolite2(GeoLite) 模块。
首先安装maxminddb-geolite2模块
pip install maxminddb-geolite2
Run Code Online (Sandbox Code Playgroud)
蟒蛇代码:
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()
Run Code Online (Sandbox Code Playgroud)
输出:
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
... ... ...
Run Code Online (Sandbox Code Playgroud)
时间:对于 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,)
Run Code Online (Sandbox Code Playgroud)
结论:大约需要。在我的硬件上使用 40 万个唯一 IP 为您提供 35 秒:
In [93]: 400000/171884*15
Out[93]: 34.90726303786274
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
1724 次 |
| 最近记录: |