Более эффективный способ добавления данных - PullRequest
1 голос
/ 14 февраля 2020

Я провел несколько тестов и обнаружил, что этот фрагмент кода здесь неэффективен. Цикл в диапазоне дат, если self.query находится в df, то добавляет строку, довольно прямо вперед. Но я слышал много мнений о том, что такое добавление неэффективно и даже ресурсоемко.
В моих паркетах 4 колонки с миллионами строк - query phone_count desktop_count total, отбрасывая 2 столбца, что означает У меня есть index, query и total, а затем происходят маги c.

Этот код работает "отлично", но теперь я ищу мнения опытных пользователей и, возможно, получаю некоторые подсказки.

Есть ли способ сделать то же самое более эффективным способом? Кортежи может быть?

Спасибо, ребята!

    for filename in os.listdir(directory):
        if filename.endswith(".parquet"):
            df = pd.read_parquet(directory).drop(["phone_count","desktop_count"], axis=1)
            df.set_index("query", inplace=True)

            if self.lowercase == "on":
                df.index = df.index.str.lower()
            else:
                pass
            if self.sensitive == "on":                            
                self.datafr = self.datafr.append(df.filter(regex=re.compile(self.query), axis=0))
            else:            
                self.datafr = self.datafr.append(df.filter(regex=re.compile(self.query, re.IGNORECASE), axis=0))            


self.datafr = self.datafr.groupby(['query']).sum().sort_values(by='total', ascending=False)

1 Ответ

2 голосов
/ 14 февраля 2020

Вы повторяете несколько вещей с каждым l oop:

  • Шаблон регулярного выражения не требует перекомпиляции каждый раз, когда
  • Повтор DataFrame.append медленнее, чем pd.concat([frame1, frame2, ...])
  • list.append намного быстрее, чем DataFrame.append

Попробуйте:

option = re.IGNORECASE if self.lowercase == "on" else 0
pattern = re.compile(self.query, option)
subframes = []

for filename in os.listdir(directory):
    if filename.endswith(".parquet"):
        df = pd.read_parquet(directory).drop(["phone_count","desktop_count"], axis=1)
        df.set_index("query", inplace=True)

        # Not sure if this statement is necessary. The regex
        # is already IGNORECASE when lowercase == "on"
        if self.lowercase == "on":
            df.index = df.index.str.lower()

        # Multiple list.append
        subframes.append(df.filter(pattern, axis=0))

# But a single pd.concat
self.datafr = pd.concat([self.datafr] + subframes)
...