#python #python-3.x #pandas #numpy
#python #python-3.x #pandas #numpy
Вопрос:
Я пытаюсь найти эффективный способ умножения каждой комбинации столбцов внутри фрейма данных pandas. Мне удалось добиться этого с помощью itertools, однако, когда размер фрейма данных увеличивается, он резко замедляется. Мне нужно будет выполнить это на фрейме данных размером около (100,1000)
Пример рабочего кода с меньшим фреймом данных приведен ниже,
import numpy as np
import pandas as pd
from itertools import combinations_with_replacement
df = pd.DataFrame(np.random.randn(3, 10))
new_df = pd.DataFrame()
for p in combinations_with_replacement(df.columns,2):
title = p
new_df[title] = df[p[0]]*df[p[1]]
У кого-нибудь есть какие-либо предложения о том, как этого можно достичь?
Комментарии:
1. Я думаю, это должно быть
O(n^2)
сложно, поскольку никакие вычисления не могут быть сохранены.
Ответ №1:
Комбинируя представление индекса и array.prod(axis)
, это выполняется в ~ 100 раз быстрее:
def f1():
#with loop
new_df = pd.DataFrame()
for p in combinations_with_replacement(df.columns,2):
title = p
new_df[title] = df[p[0]]*df[p[1]]
return new_df
def f2():
n = len(df.columns)
ix = np.indices((n,n))[:, ~np.tri(n, k=-1, dtype=bool)]
return pd.DataFrame(df.values.T[ix.T].prod(1).T, columns=list(map(tuple, ix.T)))
Комментарии:
1. В случаях, когда фрейм данных содержит значения столбцов, которые не являются просто расположением индекса, как мне установить новые заголовки столбцов, чтобы показывать результаты того, что было умножено. Например, если df следующий; df = pd.DataFrame(np.random.randn(3, 10), столбцы=[‘a’, ‘b’, ‘c’, ‘d’,’e’,’f’, ‘g’, ‘h’, ‘j’,’k’]) Я бы хотел видеть (‘a’, ‘b’) в виде столбца, а не (0,1)
2. Используйте
columns = list(map(tuple, np.array(['a','b','c','d','e','f','g','h','j','k'])[ix.T]))
. Обратите внимание, чтоlist(map(tuple
это просто для создания кортежей для заголовков столбцов,np.array(...)[ix.T]
это для создания массива буквосочетаний.