2017-04-25 24 views
0

我有一些稱爲約束矩陣,其中每個用戶(muid)可以發送一個內容(策略)最大N次。因此,我已表示它作爲一個數據幀爲:自動條件來檢查一個上閾值

tactic max_times 
100  50 
101  35 
102  23 
103  30 
........... 
......... 

命名100只有最大的50倍,101最大的35倍等,從而每個用戶可以發送策略。

現在我們必須模擬每個用戶在各種迭代中發送特定內容(策略)。

## code to simulate data 
import random 
muid=range(1,11) 
tactic=range(100,110) 

##create dataframe for first iteration 
temp=DataFrame({'muid':muid,'tactic':tactic}) 
print temp 
    muid tactic 
0 1 100 
1 2 101 
2 3 102 
3 4 103 
4 5 104 

##reshuffle the sent channel 
tactic1=random.sample(range(100,110),10) 
##dataframe for second iteration 
temp1=DataFrame({'muid':muid,'tactic':tactic1}) 
print temp1 

    muid tactic 
0 1 101 
1 2 100 
2 3 106 
3 4 107 
4 5 109 
5 6 102 
6 7 104 
7 8 108 
8 9 105 
9 10 103 

###code to calculate how many times user has been sent/exposed to a channel 
#groupby for first iteration 
groupedby=temp.groupby(['muid','tactic'])['tactic'].agg({'count':'count'}) 
groupedby.reset_index(inplace=True) 

#groupby for second iteration 
groupedby1=temp1.groupby(['muid','tactic'])['tactic'].agg({'count':'count'}) 
groupedby1.reset_index(inplace=True) 
appended_output=groupedby.append(groupedby1) 
total_counts_at_second_iteration=appended_output.groupby(['muid','tactic'])['tactic'].agg({'total_sent':'count'}) 

所以在第二次迭代之後的端輸出如下所示:

##top 8 rows 
muid tactic total_sent 
0 1 100 1 
1 1 101 1 
2 2 101 1 
3 2 107 1 
4 3 102 1 
5 3 104 1 
6 4 103 2 
7 5 102 1 
8 5 104 1 

上述輸出對應於2次迭代。現在我想把上面的代碼放在循環中(N次迭代),並且一旦達到任何發送策略的約束,該策略就不應該再發送,並且應該顯示一條消息「策略達到的限制」。任何幫助,應該感激。

回答

0

你可以使用np.random.choice,它有一個參數爲p的權重。然後,如果您跟蹤字典中每個用戶的約束條件,則可以對每種策略進行迭代,確保爲每個用戶更新每次迭代的約束/權重。大致如下的東西應該可以工作:

import pandas as pd 
import numpy as np 

muid=range(1,11) 
tactic=range(100,110) 

# individual max_constraints for each tactic 
# (Ordering must be consistent with tactic!) 
max_times=[50,35,23,30,10,50,5,12,17,22] 

total_times = sum(max_times) # total tactics given out 

# keeps track of the number of available tactics (constraints) for each user_id 
user_constraint_dict = {user_id:{idn:max_tactic for idn, max_tactic in 
zip(tactic,max_times)} for user_id in muid } 

def constraint_to_prob(constraint_dict): 

    ''' 
    convert a dictionary containing weights to probabilities 
    for use by np.random.choice 
    ''' 

    total_remaining = float(sum(constraint_dict.values())) 
    prob_dict = {tactic:constraint_num/total_remaining for tactic, constraint_num in constraint_dict.iteritems()} 

    return prob_dict 

tactic_df = pd.DataFrame(index=muid,columns=['tactic_'+str(i) for i in range(total_times)]) 

for tactic_iter in range(total_times): 

    for user_id in tactic_df.index: 

     user_weight_dict = constraint_to_prob(user_constraint_dict[user_id]) 
     user_weights = [user_weight_dict[tac] for tac in tactic] 
     chosen_tactic = np.random.choice(tactic,p=user_weights) 

     tactic_df.loc[user_id,'tactic_'+str(tactic_iter)] = chosen_tactic 

     # update constraints for the given user 
     user_constraint_dict[user_id][chosen_tactic]-=1