Почему мой питон DataFrame работает так медленно

Это решение работает с механизмом базы данных Access 2010:

Необходимая ссылка:

Microsoft.Office.interop.access.dao

Код:

public void CompactDb(
    string sourceFilePath, string destFilePath, string password)
{
    var dbEngine = new Microsoft.Office.Interop.Access.Dao.DBEngine();

    dbEngine.CompactDatabase(sourceFilePath, destFilePath,
        ";pwd=" + password, null, ";pwd=" + password);
}

(Исходные файлы и файлы destFilePath не должны быть одинаковыми!) [/ ​​g3]

Параметры метода CompactDatabase (от отражения):

void CompactDatabase(
    string SrcName, string DstName,
    object DstLocale = Type.Missing,
    object Options = Type.Missing,
    object SrcLocale = Type.Missing);

Убедитесь, что вы запустили его на той же платформе, что и AccessDatabaseEngine (или Office) (x86 / x64).

0
задан JonnyCab 16 January 2019 в 14:30
поделиться

2 ответа

Несколько комментариев о вашем коде:

  • все эти global переменные пугают меня! что не так с передачей параметров и возвращением состояния?
  • вы не используете какую-либо функциональность из Pandas, создавая фрейм данных только для того, чтобы использовать его для тупой итерации по строкам, это заставляет его выполнять много ненужной работы
  • стандартный модуль csv (может использоваться с delimiter='|') обеспечивает гораздо более тесный интерфейс, если это действительно лучший способ сделать это

это может быть лучший вопрос для https://codereview.stackexchange.com/

, просто играющих с производительностью альтернативных способов работы со строками. Из приведенного ниже поясняется, что работа «по строкам» в основном всегда медленная, когда Панды

начинают с создания кадра данных, чтобы проверить это:

import numpy as np
import pandas as pd

df = pd.DataFrame(np.random.randint(1, 1e6, (10_000, 2)))
df[1] = df[1].apply(str)

это занимает 3,65 мс для создать фрейм данных со столбцами int и str. затем я попробую подход iterrows:

tot = 0
for i, row in df.iterrows():
    tot += row[0] / 1e5 < len(row[1])

агрегация довольно тупая, я просто хотел что-то, что использует оба столбца. это занимает страшные длинные 903 мс. затем я пытаюсь выполнить итерации вручную:

tot = 0
for i in range(df.shape[0]):
    tot += df.loc[i, 0] / 1e5 < len(df.loc[i, 1])

, что сокращает это до 408 мс. затем я пытаюсь apply:

def fn(row):
    return row[0] / 1e5 < len(row[1])

sum(df.apply(fn, axis=1))

, который в основном совпадает с 368 мс. наконец, я нахожу некоторый код, которым Пандас доволен:

sum(df[0] / 1e5 < df[1].apply(len))

, что занимает 4,15 мс. и другой подход, который пришел мне в голову:

tot = 0
for a, b in zip(df[0], df[1]):
    tot += a / 1e5 < len(b)

, что занимает 2,78 мс. в то время как другой вариант:

tot = 0
for a, b in zip(df[0] / 1e5, df[1]):
    tot += a < len(b)

занимает 2,29 мс.

0
ответ дан Sam Mason 16 January 2019 в 14:30
поделиться

iterrows не использует векторизованные операции. Большинство преимуществ использования pandas исходят от векторизованных и параллельных операций.

Замените for index, row in df_wf.iterrows(): на df_wf.apply(something, axis=1), где something - это функция, которая инкапсулирует необходимую логику из iterrows и использует numpy векторизованные операции.

Также, если ваш df не помещается в памяти так, что вам нужно пакетное чтение, рассмотрите возможность использования dask или spark вместо pandas.

Дополнительное чтение: https://pandas.pydata.org/pandas-docs/stable/enhancingperf.html

0
ответ дан Charles Landau 16 January 2019 в 14:30
поделиться
Другие вопросы по тегам:

Похожие вопросы: