加速数据帧.loc()

时间:2017-02-16 12:39:48

标签: python pandas geoip

我有一个大约400k IP的列表(存储在pandas DataFrame df_IP中),使用maxming geoIP数据库进行地理定位。我使用城市版本,我检索城市,纬度,经度和县代码(在法国的部门),因为一些城市有相同的名称,但在不同的地方。

这是我的工作代码:

import geoip2.database
import pandas as pd

reader = geoip2.database.Reader('path/to/GeoLite2-City.mmdb')
results = pd.DataFrame(columns=('IP',
                                'city',
                                'latitude',
                                'longitude',
                                'dept_code'))

for i, IP in enumerate(df_IP["IP"]):
    try :
        response = reader.city(IP)
        results.loc[i] = [IP,response.city.name,response.location.latitude,response.location.longitude,response.subdivisions.most_specific.iso_code]
    except Exception as e:
        print ("error with line {}, IP {}: {}").format(i,df_IP["IP"][i],e )

效果很好,但每次循环都会变得越来越慢。如果我在1000第一个IP上计时,我需要4.7s,所以整个400k需要大约30分钟,但它运行了将近4个小时。

IMO唯一可以随着时间的推移而减速的是填充Dataframe results:我有哪些替代品不使用.loc并且可以更快?我最后还需要相同的数据帧。

我也有兴趣解释为什么loc在大型数据帧上如此之慢。

2 个答案:

答案 0 :(得分:1)

我遇到了类似的情况,因为loc导致运行时爆炸。在摆弄了很多东西后,我找到了一个超快速的简单解决方案。 使用set_value而不是loc。

这是示例代码的样子:您可以为您的用例调整它。假设您的数据框架是这样的

Index  'A'  'B' 'Label'
23      0    1    Y
45      3    2    N

self.data.set_value(45,'Label,'NA')

这将设置列"标签"的值。作为第二行的NA。

有关set_value的更多信息,请参阅以下链接:

http://pandas.pydata.org/pandas-docs/version/0.17/generated/pandas.DataFrame.set_value.html

答案 1 :(得分:0)

我遇到了同样的问题,而且@oliversm建议我创建一个列表,然后将其添加到原始数据集中。 这是代码的样子:

...

results_list=[]

for i, IP in enumerate(df_IP["IP"]):
    try :
        response = reader.city(IP)
     results_list.append( response.city.name,response.location.latitude,response.location.longitude,response.subdivisions.most_specific.iso_code)
    except Exception as e:
        print ("error with line {}, IP {}: {}").format(i,df_IP["IP"][i],e )

results_array=np.asarray(results_list) #list to array to add to the dataframe as a new column

results['results_column']=pd.Series(results_array,index=results.index)