У меня есть кадр данных из 3 столбцов. Col 1 - порядковый номер строки, Col 2 - целое число, а Col 3 - имя продукта. Я хотел бы преобразовать это в матрицу, где каждая строка представляет собой уникальную комбинацию порядок/день, и каждый столбец представляет 1/0 для наличия имени продукта для этой комбинации.Преобразование базы данных pandas в разреженную матрицу элементов с составным ключом
В моем подходе до сих пор используется словарь продукта и словарь с составным ключом порядка # & день. Заключительный шаг, который выполняет итерацию через исходный фрейм, чтобы перевернуть биты в матрице на 1s, - это sloooow. Как 10 минут для матрицы размером 363K X 331 и редкостью ~ 97%.
Есть ли другой подход, который я должен рассмотреть?
Например,
ord_nb day prod
1 1 A
1 1 B
1 2 B
1 2 C
1 2 D
станет
A B C D
1 1 0 0
0 1 1 1
Мой подход заключается в создании словаря пар заказа/день:
ord_day_dict = {}
print("Making a dictionary of ord-by-day keys...")
gp = df.groupby(['day', 'ord'])
for i,g in enumerate(gp.groups.items()):
ord_day_dict[g[0][0], g[0][1]] = i
прилагаю индекс represention к исходный дата-кадр:
df['ord_day_idx'] = 0 #Create a place holder column
for i, row in df.iterrows(): #populate the column with the index
df.set_value(i,'ord_day_idx',ord_day_dict[(row['day'], row['ord_nb'])])
Я тогда инициализировать матрицу размером моих ORD/день X уникальных продуктов:
n_items = df.prod_nm.unique().shape[0] #unique number of products
n_ord_days = len(ord_day_dict) #unique number of ord-by-day combos
df_fac_matrix = np.zeros((n_ord_days, n_items), dtype=np.float64)#-1)
конвертировать мои продукты из строки в индекс с помощью словаря:
prod_dict = dict()
i = 0
for v in df.prod:
if v not in prod_dict:
prod_dict[v] = i
i = i + 1
И, наконец, итерации через исходный блок данных, чтобы заполнить матрицу 1 с, где определенный заказ в определенный день включал конкретный продукт.
for line in df.itertuples():
df_fac_matrix[line[4], line[3]] = 1.0 #in the order-by-day index row and the product index column of our ord/day-by-prod matrix, mark a 1