2017-08-29 183 views
2

我有一个指向numpy数组的索引的熊猫数据框。对于这些索引,数组的值必须设置为1。我需要在一个庞大的阵列上做数百万次。有没有比下面显示的方法更有效的方法?使用熊猫数据框在numpy数组中设置索引

from numpy import float32, uint 
from numpy.random import choice 
from pandas import DataFrame 
from timeit import timeit 

xy = 2000,300000 
sz = 10000000 
ind = DataFrame({"i":choice(range(xy[0]),sz),"j":choice(range(xy[1]),sz)}).drop_duplicates() 
dtype = uint 
repeats = 10 

#original (~21s) 
stmt = '''\ 
from numpy import zeros 
a = zeros(xy, dtype=dtype) 
a[ind.values[:,0],ind.values[:,1]] = 1''' 

print(timeit(stmt, "from __main__ import xy,sz,ind,dtype", number=repeats)) 

#suggested by @piRSquared (~13s) 
stmt = '''\ 
from numpy import ones 
from scipy.sparse import coo_matrix 
i,j = ind.i.values,ind.j.values 
a = coo_matrix((ones(i.size, dtype=dtype), (i, j)), dtype=dtype).toarray() 
''' 

print(timeit(stmt, "from __main__ import xy,sz,ind,dtype", number=repeats)) 

我已经编辑了上面的帖子显示由@piRSquared和建议的办法(ES)重新写的,让一个苹果对苹果的比较。无论数据类型如何(尝试uint和float32),建议的方法都会将时间缩短40%。

回答

5

OP时间

56.56 s 

我只能略微有

i, j = ind.i.values, ind.j.values 
a[i, j] = 1 

新时代提高

52.19 s 

但是,可以大大利用scipy.sparse.coo_matrix加快这实例化为解析矩阵,然后将其转换为numpy.array

import timeit 

stmt = '''\ 
import numpy, pandas 
from scipy.sparse import coo_matrix 

xy = 2000,300000 

sz = 10000000 
ind = pandas.DataFrame({"i":numpy.random.choice(range(xy[0]),sz),"j":numpy.random.choice(range(xy[1]),sz)}).drop_duplicates() 

################################################ 
i, j = ind.i.values, ind.j.values 
dtype = numpy.uint8 
a = coo_matrix((numpy.ones(i.size, dtype=dtype), (i, j)), dtype=dtype).toarray()''' 

timeit.timeit(stmt, number=10) 

33.06471237000369 
+0

是的......一点点。你放弃创建'ind1'数组的开销。 “ind.i.values”和“ind.j.values”已经在那里了。 'ind.values'不会被创建。 – piRSquared

+1

@jezrael新的时间。 – piRSquared

+0

谢谢@piRSquared。我已更新原始帖子以显示您的方法并轻松进行比较。 – ironv