#python #pandas #dataframe #optimization #random
#python #pandas #фрейм данных #оптимизация #Случайный
Вопрос:
Я работаю над логикой … но это занимает больше времени, чем ожидалось…
Проблема:
-
Набор данных (A) с 60 идентификаторами продуктов
-
В наборе данных (B) около 90 тыс. клиентов
Мне нужно назначить 30 случайных уникальных идентификаторов продукта для каждого клиента…но повторения продуктов cam происходят для разных клиентов. Ниже приведен мой код:
#List of 90K customers
web_cust_temp = web_cust['prsn_code'].tolist()
default_nom_ids['key']=1
#Allocating num_default ids to each customers
num_default=30
#Create empty dataframe
final_df=pd.DataFrame()
for x in web_cust_temp:
default_nom_temp=default_nom_ids.sample(n=num_default)
prsn_df=pd.DataFrame([x])
prsn_df['key']=1
interim=prsn_df.merge(default_nom_temp, how='inner', on=['key'])
final_df=pd.concat([final_df,interim],axis=0)
Комментарии:
1. Пожалуйста, объясните свой код. Что такое
web_cust_temp
? Что такоеdefault_nom_keys
?2. @RubenHelsloot web_cust_temp: список из 90 тыс. клиентов, default_nomination_ids : фрейм данных содержит 60 идентификаторов, из которых мне нужно назначить 30 каждому из клиентов в списке web_cust_temp
3. Ключ @RubenHelsloot — это столбец, который я создал как в default_nom_ids, так и в dataframe внутри цикла (prsn_df) . Надеюсь, это устранит путаницу
4. С повторением или без повторения?
5. @wildplasser для каждого клиента …. необходимо выбрать уникальные идентификаторы…..
Ответ №1:
Одна из идей здесь заключается в использовании argsort
случайного массива для случайного выбора ровно 30 индексов для каждой строки:
m,n = 60, 90_000
# remove seed for randomization
np.random.seed(42)
seeds = np.random.rand(m,n)
idx = np.argsort(seeds, axis=0)
out = web_cust['prsn_code'].values[idx[:,:30]]
Комментарии:
1. Спасибо, позвольте мне попробовать это и вернусь к вам.
Ответ №2:
Я изменил «начальный» код для создания обоих исходных фреймов данных на:
nProd = 60
idx = range(nProd)
default_nom_ids = pd.DataFrame({'Name': ['Product_' str(i) for i in idx]}, index=idx)
default_nom_ids['key'] = 1
nCust = 1000
idx = range(nCust)
# Customer list, used in your code
web_cust_temp = ['Customer_' str(i) for i in idx]
# DataFrame version of customer list, used in my code
cust = pd.DataFrame({'Name': web_cust_temp}, index=idx)
num_default = 30
Чтобы сравнить время выполнения, я преобразовал ваш код в функцию:
def f1(num_default):
final_df = pd.DataFrame()
for x in web_cust_temp:
default_nom_temp = default_nom_ids.sample(n=num_default)
prsn_df = pd.DataFrame([x])
prsn_df['key'] = 1
interim = prsn_df.merge(default_nom_temp, how='inner', on=['key'])
final_df = pd.concat([final_df,interim], axis=0, ignore_index=True)
return final_df
И мой код я определил как другую функцию:
def f2(num_default):
tbl = []
for idxC in cust.index:
idxP = default_nom_ids.sample(n=num_default, replace=False).index
tbl.append(np.vstack([np.full(num_default, idxC), idxP]))
idx = np.hstack(tbl)
result = pd.DataFrame({'dummy': 1}, index=pd.MultiIndex.from_arrays(idx, names=['Cust', 'Prod']))
return result.join(cust, on='Cust').join(default_nom_ids, on='Prod',
lsuffix='_Cust', rsuffix='_Prod').drop(columns=['dummy', 'key'])
Используя%timeit, я сравнил время выполнения:
- ваш код: 19,6 с,
- мой код: 1.31 с.
Обратите внимание, что приведенный выше результат относится к 1000 клиентам. Если количество клиентов больше, разница во времени должна быть еще более заметной.