2016-07-19 30 views
3

Ich führe einen Codeschnipsel durch, der eine Datenbank abfragt und dann einen Pandas-Datenrahmen mit dem Wert 1 ausfüllt, wenn das Tupel in der Abfrage vorhanden ist. Dies geschieht durch Ausführen der Abfrage, iteriert dann über die Tupel und füllt den Datenrahmen aus. Die Abfrage gibt jedoch fast 8 Millionen Datenzeilen zurück.Füllwert eines Pandas-Datenrahmens aus einer großen DB-Abfrage (Python)

Meine Frage ist, ob jemand weiß, wie man einen Prozess so beschleunigt. Hier ist der folgende Code:

user_age = pd.read_sql_query(sql_age, datastore, index_col=['userid']).age.astype(np.int, copy=False) 
x = pd.DataFrame(0, index=user_age.index, columns=range(366), dtype=np.int8) 

for r in pd.read_sql_query(sql_active, datastore, chunksize=50000): 
     for userid, day in r.itertuples(index=False): 
      x.at[userid, day] = 1 

Vielen Dank im Voraus!

+2

Das ist brutal. Ich kann mir keinen schnelleren Weg vorstellen. – piRSquared

Antwort

2

Sie könnten einige Zeit durch den Austausch des Schleifen Python speichern

for userid, day in r.itertuples(index=False): 
    x.at[userid, day] = 1 

mit einer NumPy Array Zuordnung "Advanced integer Indexing" verwendet:

x[npidx[r['userid']], r['day']] = 1 

Auf einem 80000-row Datenrahmen, using_numpy (unten) ist etwa 6x schneller:

In [7]: %timeit orig() 
1 loop, best of 3: 984 ms per loop 

In [8]: %timeit using_numpy() 
10 loops, best of 3: 162 ms per loop 

import numpy as np 
import pandas as pd 

def mock_read_sql_query(): 
    np.random.seed(2016) 
    for arr in np.array_split(index, N//M): 
     size = len(arr) 
     df = pd.DataFrame({'userid':arr , 'day':np.random.randint(366, size=size)}) 
     df = df[['userid', 'day']] 
     yield df 

N, M = 8*10**4, 5*10**2 
index = np.arange(N) 
np.random.shuffle(index) 
columns = range(366) 

def using_numpy(): 
    npidx = np.empty_like(index) 
    npidx[index] = np.arange(len(index)) 
    x = np.zeros((len(index), len(columns)), dtype=np.int8) 
    for r in mock_read_sql_query(): 
     x[npidx[r['userid']], r['day']] = 1 
    x = pd.DataFrame(x, columns=columns, index=index) 
    return x 

def orig(): 
    x = pd.DataFrame(0, index=index, columns=columns, dtype=np.int8) 
    for r in mock_read_sql_query(): 
     for userid, day in r.itertuples(index=False): 
      x.at[userid, day] = 1 
    return x 

expected = orig() 
result = using_numpy() 

expected_index, expected_col = np.where(expected) 
result_index, result_col = np.where(result) 
assert np.equal(expected_index, result_index).all() 
assert np.equal(expected_col, result_col).all() 
Verwandte Themen