2017-08-29 105 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