【问题标题】:Filling Value of a Pandas Data Frame From a Large DB Query (Python)从大型数据库查询 (Python) 中填充 Pandas 数据框的值
【发布时间】:2016-07-20 10:00:43
【问题描述】:

我正在运行一个查询数据库的代码 sn-p,然后如果查询中存在该元组,则使用值 1 填充 pandas 数据帧。它通过运行查询然后迭代元组并填充数据框来做到这一点。但是,该查询返回了近 800 万行数据。

我的问题是,是否有人知道如何加快这样的过程。下面是代码:

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

提前谢谢你!

【问题讨论】:

  • 这太残忍了。我想不出更快的方法。

标签: python-2.7 pandas optimization dataframe


【解决方案1】:

您可以通过替换 Python 循环来节省一些时间

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

使用“高级整数索引”进行 NumPy 数组赋值:

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

在 80000 行的 DataFrame 上,using_numpy(下图)大约快 6 倍:

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()

【讨论】:

    猜你喜欢
    • 2018-08-13
    • 1970-01-01
    • 2011-03-11
    • 2020-06-27
    • 1970-01-01
    • 2019-03-21
    • 2013-06-10
    • 1970-01-01
    • 2020-11-26
    相关资源
    最近更新 更多