婚戀配對實驗


 

婚戀配對實驗

婚戀配對模擬規則:
① 按照一定規則生成了1萬男性+1萬女性樣本:
   ** 在配對實驗中,這2萬個樣本具有各自不同的個人屬性(財富、內涵、外貌),每項屬性都有一個得分
   ** 財富值符合指數分布,內涵和顏值符合正態分布
   ** 三項的平均值都為60分,標准差都為15分
② 模擬實驗。基於現實世界的提煉及適度簡化,我們概括了三個最主流的擇偶策略:
   ** 擇偶策略1:門當戶對,要求雙方三項指標加和的總分接近,差值不超過20分;
   ** 擇偶策略2:男才女貌,男性要求女性的外貌分比自己高出至少10分,女性要求男性的財富分比自己高出至少10分;
   ** 擇偶策略3:志趣相投、適度引領,要求對方的內涵得分在比自己低5分~高10分的區間內,且外貌和財富兩項與自己的得分差值都在5分以內
③ 每一輪實驗中,我們將三種策略隨機平分給所有樣本(即采用每種策略的男性有3333個樣本)
④ 我們為每位單身男女隨機選擇一個對象,若雙方互相符合要求就算配對成功,配對失敗的男女則進入下一輪配對。

1、樣本數據處理
   ** 按照一定規則生成了1萬男性+1萬女性樣本:
   ** 在配對實驗中,這2萬個樣本具有各自不同的個人屬性(財富、內涵、外貌),每項屬性都有一個得分
   ** 財富值符合指數分布,內涵和顏值符合正態分布
   ** 三項的平均值都為60分,標准差都為15分
要求:
① 構建函數實現樣本數據生成模型,函數參數之一為“樣本數量”,並用該模型生成1萬男性+1萬女性數據樣本
   ** 包括三個指標:財富、內涵、外貌
② 繪制柱狀圖來查看每個人的屬性分值情況
提示:
① 正態分布:np.random.normal(loc=60, scale=15, size=n)
② 指數分布:np.random.exponential(scale=15, size=n) + 45

2、生成99個男性、99個女性樣本數據,分別針對三種策略構建算法函數
   ** 擇偶策略1:門當戶對,要求雙方三項指標加和的總分接近,差值不超過20分;
   ** 擇偶策略2:男才女貌,男性要求女性的外貌分比自己高出至少10分,女性要求男性的財富分比自己高出至少10分;
   ** 擇偶策略3:志趣相投、適度引領,要求對方的內涵得分在比自己低10分~高10分的區間內,且外貌和財富兩項與自己的得分差值都在5分以內
   ** 每一輪實驗中,我們將三種策略隨機平分給所有樣本,這里則是三種策略分別33人
   ** 這里不同策略匹配結果可能重合,所以為了簡化模型 
   → 先進行策略1模擬,
   → 模擬完成后去掉該輪成功匹配的女性數據,再進行策略2模擬,
   → 模擬完成后去掉該輪成功匹配的女性數據,再進行策略3模擬
① 生成樣本數據
② 給男性樣本數據,隨機分配策略選擇 → 這里以男性為出發作為策略選擇方
③ 嘗試做第一輪匹配,記錄成功的匹配對象,並篩選出失敗的男女性進入下一輪匹配
④ 構建模型,並模擬1萬男性+1萬女性的配對實驗
⑤ 通過數據分析,回答幾個問題:
   ** 百分之多少的樣本數據成功匹配到了對象?
   ** 采取不同擇偶策略的匹配成功率分別是多少?
   ** 采取不同擇偶策略的男性各項平均分是多少?
提示:
① 擇偶策略評判標准:
   ** 若匹配成功,則該男性與被匹配女性在這一輪都算成功,並退出游戲
   ** 若匹配失敗,則該男性與被匹配女性再則一輪都算失敗,並進入下一輪
   ** 若同時多個男性選擇了同一個女性,且滿足成功配對要求,則綜合評分高的男性算為匹配成功
② 構建空的數據集,用於存儲匹配成功的數據
③ 每一輪匹配之后,刪除成功匹配的數據之后,進入下一輪,這里刪除數據用df.drop()
④ 這里建議用while去做迭代 → 當該輪沒有任何配對成功,則停止實驗

3、以99男+99女的樣本數據,繪制匹配折線圖
要求:
① 生成樣本數據,模擬匹配實驗
② 生成繪制數據表格
③ bokhe制圖
   ** 這里設置圖例,並且可交互(消隱模式)
提示:
① bokeh制圖時,y軸為男性,x軸為女性
② 繪制數據表格中,需要把男女性的數字編號提取出來,這樣圖表橫縱軸好識別
③ bokhe繪制折線圖示意:p.line([0,女性數字編號,女性數字編號],[男性數字編號,男性數字編號,0])

4、生成“不同類型男女配對成功率”矩陣圖
要求:
① 以之前1萬男+1萬女實驗的結果為數據
② 按照財富值、內涵值、外貌值分別給三個區間,以區間來評判“男女類型”
   ** 高分(70-100分),中分(50-70分),低分(0-50分)
   ** 按照此類分布,男性女性都可以分為27中類型:財高品高顏高、財高品中顏高、財高品低顏高、... (財→財富,品→內涵,顏→外貌)
③ bokhe制圖
   ** 散點圖
   ** 27行*27列,散點的顏色深淺代表匹配成功率
提示:
① 注意繪圖的數據結構
② 這里散點圖通過xy軸定位數據,然后通過設置顏色的透明度來表示匹配成功率
③ alpha字段為每種類型匹配成功率標准化之后的結果,再乘以一個參數
   → data['alpha'] = (data['chance'] - data['chance'].min())/(data['chance'].max() - data['chance'].min())*8   

 

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import os
import time
# 導入時間模塊

import warnings
warnings.filterwarnings('ignore') 
# 不發出警告

from bokeh.io import output_notebook
output_notebook()
# 導入notebook繪圖模塊

from bokeh.plotting import figure,show
from bokeh.models import ColumnDataSource,HoverTool
# 導入bokeh繪圖模塊

 

1、樣本數據處理
   ** 按照一定規則生成了1萬男性+1萬女性樣本:
   ** 在配對實驗中,這2萬個樣本具有各自不同的個人屬性(財富、內涵、外貌),每項屬性都有一個得分
   ** 財富值符合指數分布,內涵和顏值符合正態分布
   ** 三項的平均值都為60分,標准差都為15分
要求:
① 構建函數實現樣本數據生成模型,函數參數之一為“樣本數量”,並用該模型生成1萬男性+1萬女性數據樣本
   ** 包括三個指標:財富、內涵、外貌
② 繪制柱狀圖來查看每個人的屬性分值情況
提示:
① 正態分布:np.random.normal(loc=60, scale=15, size=n)
② 指數分布:np.random.exponential(scale=15, size=n) + 45

 

# 分別生成1萬條隨機數據,分別為正態分布、指數分布,要求數據均值為60,標准差為15

data_norm = pd.DataFrame({'正態分布':np.random.normal(loc = 60,scale = 15,size = 10000)})
data_exp = pd.DataFrame({'指數分布':np.random.exponential(scale=15, size=10000) + 45})
# 構建樣本數據 → 正態分布/指數分布

fig,axes = plt.subplots(1,2,figsize = (12,4))
data_norm.hist(bins=50,ax = axes[0],grid = True,color = 'gray',alpha = 0.6)
data_exp.hist(bins = 50,ax = axes[1],grid = True,color = 'gray',alpha = 0.6)
plt.show()

# 構建函數實現樣本數據生成模型,函數參數之一為“樣本數量”,並用該模型生成1萬男性+1萬女性數據樣本

def create_sample(n,gender):
    sample_data = pd.DataFrame({'fortune':np.random.exponential(scale=15, size=n) + 45,
                                'apperance':np.random.normal(loc = 60,scale = 15,size = n),
                                'character':np.random.normal(loc = 60,scale = 15,size = n)},
                               index = [gender + str(i) for i in range(1,n+1)])
    sample_data.index.name = 'id'
    sample_data['score'] = sample_data.sum(axis = 1)/3
    # 計算綜合評分
    return sample_data
# 創建函數

sample_m = create_sample(10000,'m')
sample_f = create_sample(10000,'f')
# 生成男女樣本數據

fig,axes = plt.subplots(2,1,figsize = (12,8))
sample_m[['apperance','character','fortune']].iloc[:50].plot(kind='bar',colormap='Blues_r',grid = True,stacked=True,ax = axes[0],ylim = [0,300]) 
sample_f[['apperance','character','fortune']].iloc[:50].plot(kind='bar',colormap='Reds_r',grid = True,stacked=True,ax = axes[1],ylim = [0,300]) 
plt.show()
# 出圖查看數據

sample_m.head()
# 查看男性樣本數據分布

2、生成99個男性、99個女性樣本數據,分別針對三種策略構建算法函數
   ** 擇偶策略1:門當戶對,要求雙方三項指標加和的總分接近,差值不超過20分;
   ** 擇偶策略2:男才女貌,男性要求女性的外貌分比自己高出至少10分,女性要求男性的財富分比自己高出至少10分;
   ** 擇偶策略3:志趣相投、適度引領,要求對方的內涵得分在比自己低10分~高10分的區間內,且外貌和財富兩項與自己的得分差值都在5分以內
   ** 每一輪實驗中,我們將三種策略隨機平分給所有樣本,這里則是三種策略分別33人
   ** 這里不同策略匹配結果可能重合,所以為了簡化模型 
   → 先進行策略1模擬,
   → 模擬完成后去掉該輪成功匹配的女性數據,再進行策略2模擬,
   → 模擬完成后去掉該輪成功匹配的女性數據,再進行策略3模擬
要求:
① 生成樣本數據
② 給男性樣本數據,隨機分配策略選擇 → 這里以男性為出發作為策略選擇方
③ 嘗試做第一輪匹配,記錄成功的匹配對象,並篩選出失敗的男女性進入下一輪匹配
④ 構建模型,並模擬1萬男性+1萬女性的配對實驗
⑤ 通過數據分析,回答幾個問題:
   ** 百分之多少的樣本數據成功匹配到了對象?
   ** 采取不同擇偶策略的匹配成功率分別是多少?
   ** 采取不同擇偶策略的男性各項平均分是多少?
提示:
① 擇偶策略評判標准:
   ** 若匹配成功,則該男性與被匹配女性在這一輪都算成功,並退出游戲
   ** 若匹配失敗,則該男性與被匹配女性再則一輪都算失敗,並進入下一輪
   ** 若同時多個男性選擇了同一個女性,且滿足成功配對要求,則綜合評分高的男性算為匹配成功
② 構建空的數據集,用於存儲匹配成功的數據
③ 每一輪匹配之后,刪除成功匹配的數據之后,進入下一輪,這里刪除數據用df.drop()
④ 這里建議用while去做迭代 → 當該輪沒有任何配對成功,則停止實驗

 

 

# 這里先生成99個男性、99個女性樣本數據

sample_m_test = create_sample(99,'m')
sample_f_test = create_sample(99,'f')
# 設置好樣本數據

sample_m_test['strategy'] = np.random.choice([1,2,3],99)
# 給男性賦值策略選擇
# 1 → 擇偶策略1
# 2 → 擇偶策略2
# 3 → 擇偶策略3

 

 

# 擇偶策略,測試

match_success = pd.DataFrame(columns = ['m','f','round_n','strategy_type'])
# 構建空的數據集,用於存儲匹配成功的數據

round1_f = sample_f_test.copy()  
# 復制女性樣本數據

round1_m = sample_m_test.copy()
round1_m['choice'] = np.random.choice(round1_f.index,len(round1_m))      
# 復制男性樣本數據,並做匹配選擇

round1_match = pd.merge(round1_m,round1_f,left_on = 'choice',right_index = True).reset_index()
round1_match['score_dis'] = np.abs(round1_match['score_x'] - round1_match['score_y'])                 # 計算綜合評分差值
round1_match['cha_dis'] = np.abs(round1_match['character_x'] - round1_match['character_y'])           # 求出內涵得分差值
round1_match['for_dis'] = np.abs(round1_match['fortune_x'] - round1_match['fortune_y'])               # 求出財富得分差值
round1_match['app_dis'] = np.abs(round1_match['apperance_x'] - round1_match['apperance_y'])           # 求出外貌得分差值
# 合並數據 

# ① 策略1:門當戶對,要求雙方三項指標加和的總分接近,差值不超過20分;
round1_s1_m = round1_match[round1_match['strategy'] == 1]                                         # 篩選策略1的數據 
round1_s1_success = round1_s1_m[round1_s1_m['score_dis'] <= 20].groupby('choice').max()           # 篩選符合要求的數據
round1_s1_success = pd.merge(round1_s1_success,round1_m.reset_index(),left_on = 'score_x',right_on = 'score')[['id_y','choice']]
round1_s1_success.columns = ['m','f']
round1_s1_success['strategy_type'] = 1
round1_s1_success['round_n'] = 1    # 得到策略1的成功匹配的結果
round1_match.index = round1_match['choice']
round1_match = round1_match.drop(round1_s1_success['f'].tolist())  # 刪除策略1成功匹配的女性數據

# ② 策略2:男才女貌,男性要求女性的外貌分比自己高出至少10分,女性要求男性的財富分比自己高出至少10分;
round1_s2_m = round1_match[round1_match['strategy'] == 2]                                          # 篩選策略2的數據 
round1_s2_success = round1_s2_m[(round1_s2_m['fortune_x'] - round1_s2_m['fortune_y'] >= 10) &      # 男性財富比女性高出至少10分
                               (round1_s2_m['apperance_y'] - round1_s2_m['apperance_x'] >= 10)]    # 女性顏值比男性高出至少10分
round1_s2_success = round1_s2_success.groupby('choice').max()                                      # 篩選符合要求的數據
round1_s2_success = pd.merge(round1_s2_success,round1_m.reset_index(),left_on = 'score_x',right_on = 'score')[['id_y','choice']]
round1_s2_success.columns = ['m','f']
round1_s2_success['strategy_type'] = 2
round1_s2_success['round_n'] = 1    # 得到策略2的成功匹配的結果
round1_match.index = round1_match['choice']
round1_match = round1_match.drop(round1_s2_success['f'].tolist())  # 刪除策略2成功匹配的女性數據

# ③ 策略3:志趣相投、適度引領,要求對方的內涵得分在比自己低10分~高10分的區間內,且外貌和財富兩項與自己的得分差值都在5分以內
round1_s3_m = round1_match[round1_match['strategy'] == 3]                                          # 篩選策略3的數據 
round1_s3_success = round1_s3_m[(round1_s3_m['cha_dis'] <10) &   # 內涵得分差在10分以內
                               (round1_s3_m['for_dis'] < 5 )&    # 財富得分差在5分以內
                               (round1_s3_m['app_dis'] < 5 )]    # 外貌得分差在5分以內
round1_s3_success = round1_s3_success.groupby('choice').max()                                      # 篩選符合要求的數據
round1_s3_success = pd.merge(round1_s3_success,round1_m.reset_index(),left_on = 'score_x',right_on = 'score')[['id_y','choice']]
round1_s3_success.columns = ['m','f']
round1_s3_success['strategy_type'] = 3
round1_s3_success['round_n'] = 1    # 得到策略3的成功匹配的結果

# 篩選出成功匹配數據
match_success = pd.concat([match_success,round1_s1_success,round1_s2_success,round1_s3_success])

# 篩選出下一輪實驗數據
round2_m = round1_m.drop(match_success['m'].tolist())
round2_f = round1_f.drop(match_success['f'].tolist())

match_success.head()

 

 

# 構建模型

def different_strategy(data_m,data_f,roundnum):
    # 創建函數 → 
    # 根據輸入的該輪男女數據,得到匹配后數據,並做指標運算
    # 根據匹配好的數據,根據不同策略輸出成功匹配的數據
    
    data_m['choice'] = np.random.choice(data_f.index,len(data_m))      
    # 根據男性樣本數據做匹配選擇
    round_match = pd.merge(data_m,data_f,left_on = 'choice',right_index = True).reset_index()
    round_match['score_dis'] = np.abs(round_match['score_x'] - round_match['score_y'])                 # 計算綜合評分差值
    round_match['cha_dis'] = np.abs(round_match['character_x'] - round_match['character_y'])           # 求出內涵得分差值
    round_match['for_dis'] = np.abs(round_match['fortune_x'] - round_match['fortune_y'])               # 求出財富得分差值
    round_match['app_dis'] = np.abs(round_match['apperance_x'] - round_match['apperance_y'])           # 求出外貌得分差值
    # 合並數據 
    
    # 策略1:門當戶對,要求雙方三項指標加和的總分接近,差值不超過20分;
    s1_m = round_match[round_match['strategy'] == 1]                                      
    s1_success = s1_m[s1_m['score_dis'] <= 20].groupby('choice').max()               
    s1_success = pd.merge(s1_success,data_m.reset_index(),left_on = 'score_x',right_on = 'score')[['id_y','choice']]
    s1_success.columns = ['m','f']
    s1_success['strategy_type'] = 1
    s1_success['round_n'] = roundnum    # 得到策略1的成功匹配的結果
    round_match.index = round_match['choice']
    round_match = round_match.drop(s1_success['f'].tolist())  # 刪除策略1成功匹配的女性數據

    # 策略2:男才女貌,男性要求女性的外貌分比自己高出至少10分,女性要求男性的財富分比自己高出至少10分;
    s2_m = round_match[round_match['strategy'] == 2]                                          
    s2_success = s2_m[(s2_m['fortune_x'] - s2_m['fortune_y'] >= 10) & (s2_m['apperance_y'] - s2_m['apperance_x'] >= 10)] 
    s2_success = s2_success.groupby('choice').max()                               
    s2_success = pd.merge(s2_success,data_m.reset_index(),left_on = 'score_x',right_on = 'score')[['id_y','choice']]
    s2_success.columns = ['m','f']
    s2_success['strategy_type'] = 2
    s2_success['round_n'] = roundnum    # 得到策略2的成功匹配的結果
    round_match.index = round_match['choice']
    round_match = round_match.drop(s2_success['f'].tolist())  # 刪除策略2成功匹配的女性數據

    # 策略3:志趣相投、適度引領,要求對方的內涵得分在比自己低10分~高10分的區間內,且外貌和財富兩項與自己的得分差值都在5分以內
    s3_m = round_match[round_match['strategy'] == 3]                                          
    s3_success = s3_m[(s3_m['cha_dis'] <10) & (s3_m['for_dis'] < 5 ) & (s3_m['app_dis'] < 5 )]    
    s3_success = s3_success.groupby('choice').max()                                     
    s3_success = pd.merge(s3_success,data_m.reset_index(),left_on = 'score_x',right_on = 'score')[['id_y','choice']]
    s3_success.columns = ['m','f']
    s3_success['strategy_type'] = 3
    s3_success['round_n'] = roundnum    # 得到策略3的成功匹配的結果
    
    # 該輪成功匹配數據
    data_success = pd.concat([s1_success, s2_success, s3_success])
    
    return data_success

print('finished!')

 

# 模型運行
# 這里建議用while去做迭代 → 當該輪沒有任何配對成功,則停止實驗

sample_m1 = create_sample(10000,'m')
sample_f1 = create_sample(10000,'f')
sample_m1['strategy'] = np.random.choice([1,2,3],10000)
# 設置好樣本數據

test_m1 = sample_m1.copy()
test_f1 = sample_f1.copy()
# 復制數據

n = 1
# 設定實驗次數變量

starttime = time.time()
# 記錄起始時間

success_roundn = different_strategy(test_m1, test_f1,n)    
match_success1 = success_roundn                                      
test_m1 = test_m1.drop(success_roundn['m'].tolist())
test_f1 = test_f1.drop(success_roundn['f'].tolist())
print('成功進行第%i輪實驗,本輪實驗成功匹配%i對,總共成功匹配%i對,還剩下%i位男性和%i位女性' % 
      (n,len(success_roundn),len(match_success1),len(test_m1),len(test_f1)))
# 第一輪實驗測試

while len(success_roundn) !=0:
    n += 1
    success_roundn = different_strategy(test_m1,test_f1,n)   
    #得到該輪成功匹配數據
    match_success1 = pd.concat([match_success1,success_roundn])           
    # 將成功匹配數據匯總
    test_m1 = test_m1.drop(success_roundn['m'].tolist())
    test_f1 = test_f1.drop(success_roundn['f'].tolist())
    # 輸出下一輪實驗數據
    print('成功進行第%i輪實驗,本輪實驗成功匹配%i對,總共成功匹配%i對,還剩下%i位男性和%i位女性' % 
          (n,len(success_roundn),len(match_success1),len(test_m1),len(test_f1)))
# 運行模型

endtime = time.time()
# 記錄結束時間

print('------------')
print('本次實驗總共進行了%i輪,配對成功%i對\n------------' % (n,len(match_success1)))
print('實驗總共耗時%.2f秒' % (endtime - starttime))

 

# 通過數據分析,回答幾個問題:
#   ** 百分之多少的樣本數據成功匹配到了對象?
#   ** 采取不同擇偶策略的匹配成功率分別是多少?
#   ** 采取不同擇偶策略的男性各項平均分是多少?

# ① 百分之多少的樣本數據成功匹配到了對象?
print('%.2f%%的樣本數據成功匹配到了對象\n---------' % (len(match_success1)/len(sample_m1)*100))

# ② 采取不同擇偶策略的匹配成功率分別是多少?
print('擇偶策略1的匹配成功率為%.2f%%' % (len(match_success1[match_success1['strategy_type']==1])/len(sample_m1[sample_m1['strategy'] == 1])*100))
print('擇偶策略2的匹配成功率為%.2f%%' % (len(match_success1[match_success1['strategy_type']==2])/len(sample_m1[sample_m1['strategy'] == 2])*100))
print('擇偶策略3的匹配成功率為%.2f%%' % (len(match_success1[match_success1['strategy_type']==3])/len(sample_m1[sample_m1['strategy'] == 3])*100))
print('\n---------')

# ③ 采取不同擇偶策略的男性各項平均分是多少?
match_m1 = pd.merge(match_success1,sample_m1,left_on = 'm',right_index = True)
result_df = pd.DataFrame([{'財富均值':match_m1[match_m1['strategy_type'] == 1]['fortune'].mean(),
                          '內涵均值':match_m1[match_m1['strategy_type'] == 1]['character'].mean(),
                          '外貌均值':match_m1[match_m1['strategy_type'] == 1]['apperance'].mean()},
                         {'財富均值':match_m1[match_m1['strategy_type'] == 2]['fortune'].mean(),
                          '內涵均值':match_m1[match_m1['strategy_type'] == 2]['character'].mean(),
                          '外貌均值':match_m1[match_m1['strategy_type'] == 2]['apperance'].mean()},
                         {'財富均值':match_m1[match_m1['strategy_type'] == 3]['fortune'].mean(),
                          '內涵均值':match_m1[match_m1['strategy_type'] == 3]['character'].mean(),
                          '外貌均值':match_m1[match_m1['strategy_type'] == 3]['apperance'].mean()}],
                         index = ['擇偶策略1','擇偶策略2','擇偶策略3'])
# 構建數據dataframe

print('擇偶策略1的男性 → 財富均值為%.2f,內涵均值為%.2f,外貌均值為%.2f' % 
      (result_df.loc['擇偶策略1']['財富均值'],result_df.loc['擇偶策略1']['內涵均值'],result_df.loc['擇偶策略1']['外貌均值']))
print('擇偶策略2的男性 → 財富均值為%.2f,內涵均值為%.2f,外貌均值為%.2f' % 
      (result_df.loc['擇偶策略2']['財富均值'],result_df.loc['擇偶策略2']['內涵均值'],result_df.loc['擇偶策略2']['外貌均值']))
print('擇偶策略3的男性 → 財富均值為%.2f,內涵均值為%.2f,外貌均值為%.2f' % 
      (result_df.loc['擇偶策略3']['財富均值'],result_df.loc['擇偶策略3']['內涵均值'],result_df.loc['擇偶策略3']['外貌均值']))

match_m1.boxplot(column = ['fortune','character','apperance'],by='strategy_type',figsize = (10,6),layout = (1,3))
plt.ylim(0,150)
plt.show()
# 繪制箱型圖

result_df

 

 

3、以99男+99女的樣本數據,繪制匹配折線圖
要求:
① 生成樣本數據,模擬匹配實驗
② 生成繪制數據表格
③ bokhe制圖
   ** 這里設置圖例,並且可交互(消隱模式)
提示:
① bokeh制圖時,y軸為男性,x軸為女性
② 繪制數據表格中,需要把男女性的數字編號提取出來,這樣圖表橫縱軸好識別
③ bokhe繪制折線圖示意:p.line([0,女性數字編號,女性數字編號],[男性數字編號,男性數字編號,0])

 

# 生成樣本數據,模擬匹配實驗

sample_m2 = create_sample(99,'m')
sample_f2 = create_sample(99,'f')
sample_m2['strategy'] = np.random.choice([1,2,3],99)
# 設置好樣本數據

test_m2 = sample_m2.copy()
test_f2 = sample_f2.copy()
# 復制數據

n = 1
# 設定實驗次數變量

starttime = time.time()
# 記錄起始時間

success_roundn = different_strategy(test_m2, test_f2,n)    
match_success2 = success_roundn                                      
test_m2 = test_m2.drop(success_roundn['m'].tolist())
test_f2 = test_f2.drop(success_roundn['f'].tolist())
print('成功進行第%i輪實驗,本輪實驗成功匹配%i對,總共成功匹配%i對,還剩下%i位男性和%i位女性' % 
      (n,len(success_roundn),len(match_success2),len(test_m2),len(test_f2)))
# 第一輪實驗測試

while len(success_roundn) !=0:
    n += 1
    success_roundn = different_strategy(test_m2,test_f2,n)   
    #得到該輪成功匹配數據
    match_success2 = pd.concat([match_success2,success_roundn])           
    # 將成功匹配數據匯總
    test_m2 = test_m2.drop(success_roundn['m'].tolist())
    test_f2 = test_f2.drop(success_roundn['f'].tolist())
    # 輸出下一輪實驗數據
    print('成功進行第%i輪實驗,本輪實驗成功匹配%i對,總共成功匹配%i對,還剩下%i位男性和%i位女性' % 
          (n,len(success_roundn),len(match_success2),len(test_m2),len(test_f2)))
# 運行模型

endtime = time.time()
# 記錄結束時間

print('------------')
print('本次實驗總共進行了%i輪,配對成功%i對\n------------' % (n,len(match_success2)))
print('實驗總共耗時%.2f秒' % (endtime - starttime))

 

 

# 生成繪制數據表格

from bokeh.palettes import brewer
# 導入調色模塊

# 設置調色盤
graphdata1 = match_success2.copy()
graphdata1 = pd.merge(graphdata1,sample_m2,left_on = 'm',right_index = True)
graphdata1 = pd.merge(graphdata1,sample_f2,left_on = 'f',right_index = True)
# 合並數據,得到成功配對的男女各項分值

graphdata1['x'] = '0,' + graphdata1['f'].str[1:] + ',' + graphdata1['f'].str[1:]
graphdata1['x'] = graphdata1['x'].str.split(',')
graphdata1['y'] = graphdata1['m'].str[1:] + ',' + graphdata1['m'].str[1:] + ',0'
graphdata1['y'] = graphdata1['y'].str.split(',')
# 篩選出id的數字編號,制作x,y字段

round_num = graphdata1['round_n'].max()
color = brewer['Blues'][round_num+1]   # 這里+1是為了得到一個色帶更寬的調色盤,避免最后一個顏色太淺
graphdata1['color'] = ''
for rn in graphdata1['round_n'].value_counts().index:
    graphdata1['color'][graphdata1['round_n'] == rn] = color[rn-1] 
# 設置顏色

graphdata1 = graphdata1[['m','f','strategy_type','round_n','score_x','score_y','x','y','color']]
# 篩選字段

graphdata1.head()

 

# bokeh繪圖

p = figure(plot_width=500, plot_height=500,title="配對實驗過程模擬示意" ,tools= 'reset,wheel_zoom,pan')   # 構建繪圖空間

for datai in graphdata1.values:
    p.line(datai[-3],datai[-2],line_width=1, line_alpha = 0.8, line_color = datai[-1],line_dash = [10,4],legend= 'round %i' % datai[3])  
    # 繪制折線
    p.circle(datai[-3],datai[-2],size = 3,color = datai[-1],legend= 'round %i' % datai[3])
    # 繪制點

p.ygrid.grid_line_dash = [6, 4]
p.xgrid.grid_line_dash = [6, 4]
p.legend.location = "top_right"
p.legend.click_policy="hide"
# 設置其他參數

show(p)

 

4、生成“不同類型男女配對成功率”矩陣圖
要求:
① 以之前1萬男+1萬女實驗的結果為數據
② 按照財富值、內涵值、外貌值分別給三個區間,以區間來評判“男女類型”
   ** 高分(70-100分),中分(50-70分),低分(0-50分)
   ** 按照此類分布,男性女性都可以分為27中類型:財高品高顏高、財高品中顏高、財高品低顏高、... (財→財富,品→內涵,顏→外貌)
③ bokhe制圖
   ** 散點圖
   ** 27行*27列,散點的顏色深淺代表匹配成功率
提示:
① 注意繪圖的數據結構
② 這里散點圖通過xy軸定位數據,然后通過設置顏色的透明度來表示匹配成功率
③ alpha字段為每種類型匹配成功率標准化之后的結果,再乘以一個參數
   → data['alpha'] = (data['chance'] - data['chance'].min())/(data['chance'].max() - data['chance'].min())*8   

 

# 數據清洗

graphdata2 = match_success1.copy()
graphdata2 = pd.merge(graphdata2,sample_m1,left_on = 'm',right_index = True)
graphdata2 = pd.merge(graphdata2,sample_f1,left_on = 'f',right_index = True)
# 合並數據,得到成功配對的男女各項分值

graphdata2 = graphdata2[['m','f','apperance_x','character_x','fortune_x','apperance_y','character_y','fortune_y']]
# 篩選字段

graphdata2['for_m'] = pd.cut(graphdata2['fortune_x'],[0,50,70,500],labels = ['財低','財中','財高'])
graphdata2['cha_m'] = pd.cut(graphdata2['character_x'],[0,50,70,500],labels = ['品低','品中','品高'])
graphdata2['app_m'] = pd.cut(graphdata2['apperance_x'],[0,50,70,500],labels = ['顏低','顏中','顏高'])
graphdata2['for_f'] = pd.cut(graphdata2['fortune_y'],[0,50,70,500],labels = ['財低','財中','財高'])
graphdata2['cha_f'] = pd.cut(graphdata2['character_y'],[0,50,70,500],labels = ['品低','品中','品高'])
graphdata2['app_f'] = pd.cut(graphdata2['apperance_y'],[0,50,70,500],labels = ['顏低','顏中','顏高'])
# 指標區間划分

graphdata2['type_m'] = graphdata2['for_m'].astype(np.str) + graphdata2['cha_m'].astype(np.str) + graphdata2['app_m'].astype(np.str)
graphdata2['type_f'] = graphdata2['for_f'].astype(np.str) + graphdata2['cha_f'].astype(np.str) + graphdata2['app_f'].astype(np.str) 

graphdata2 = graphdata2[['m','f','type_m','type_f']]
# 篩選字段

graphdata2.head()

 

# 匹配成功率計算

success_n = len(graphdata2)
success_chance = graphdata2.groupby(['type_m','type_f']).count().reset_index()
success_chance['chance'] = success_chance['m']/success_n
success_chance['alpha'] = (success_chance['chance'] - success_chance['chance'].min())/(success_chance['chance'].max() - success_chance['chance'].min())*8   # 設置alpha參數
success_chance.head()

 

# bokeh繪圖

mlst = success_chance['type_m'].value_counts().index.tolist()
flst = success_chance['type_f'].value_counts().index.tolist()
source = ColumnDataSource(success_chance)    # 創建數據
hover = HoverTool(tooltips=[("男性類別", "@type_m"),
                           ("女性類別","@type_f"),
                           ("匹配成功率","@chance")]) # 設置標簽顯示內容

p = figure(plot_width=800, plot_height=800,x_range = mlst, y_range = flst,
           title="不同類型男女配對成功率" ,x_axis_label = '', y_axis_label = '',    # X,Y軸label
           tools= [hover,'reset,wheel_zoom,pan,lasso_select'])   # 構建繪圖空間

p.square_cross(x = 'type_m', y = 'type_f', source = source,size = 18 ,color = 'red',alpha = 'alpha')
# 繪制點

p.ygrid.grid_line_dash = [6, 4]
p.xgrid.grid_line_dash = [6, 4]
p.xaxis.major_label_orientation = "vertical"
# 設置其他參數

show(p)

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM