根据属性将两个人配对在一起

PPa*_*ker 3 python algorithm match dataframe pandas

我有一个与其他人的数据框。每行都包含表征个人的属性。基本上,我需要权重特定属性的过滤器或匹配算法之类的东西。数据框如下所示:

df= pd.DataFrame({
'sex' : [m,f,m,f,m,f],
'food' : [0,0,1,3,4,3],
 'age': [young, young, young, old, young, young]
'kitchen': [0,1,2,0,1,2],
})
Run Code Online (Sandbox Code Playgroud)

数据框df如下所示:

    sex food  age     kitchen
0   m    0    young    0
1   f    0    young    1
2   m    1    young    2
3   f    3    old      0
4   m    4    young    1
5   f    3    young    2
Run Code Online (Sandbox Code Playgroud)

我正在寻找一种算法,将数据帧中的所有人员分组。我的计划是根据以下属性找到两个人对:

  1. 一个人必须有厨房(厨房= 1)
    。重要的是至少一个人要有厨房。

    kitchen = 0->人没有厨房

    kitchen = 1->人有厨房

    kitchen = 2->人有厨房,但只有在紧急情况下(当没有其他选择时)

  2. 相同的食物偏好

    食物= 0->肉食者

    食物= 1->没关系

    食物= 2->素食主义者

    食物= 3->素食

    食肉者(food = 0)可以与一个不在乎食物偏爱(food = 1)但不能与素食主义者或素食主义者相匹配的人搭配。素食主义者(食物= 2)最适合素食主义者(食物= 3),并且在必要时可以搭配食物= 1。等等...

  3. 相似年龄

    共有9个年龄段:10-18岁;18-22; 22-26; 26-29、29-34;34-40; 40-45;45-55和55-75。同一年龄段的人匹配得很好。年轻的年龄段与年龄较大的年龄段的匹配度不是很好。相似年龄段的人匹配得更好。没有明确定义的条件。“旧”和“年轻”的含义是相对的。

性别无关紧要。有许多可能的配对组合。因为我的实际数据帧很长(3000行),所以我需要找到一个自动化的解决方案。一种解决方案,可为我提供数据帧或字典或其他内容中的最佳配对。

我真的不知道如何解决这个问题。我一直在寻找Stack Overflow上的类似问题,但没有找到合适的方法。在大多数情况下,这只是理论上的问题。我也找不到任何真正适合我的问题的东西。

我在这里的预期输出是,例如字典(不确定如何)或数据帧,其排序方式是每两行可以看作一对。

背景:目标是结伴参加一些业余活动。因此,我认为处于相同或相似年龄段的人们具有相同的兴趣,因此我想在我的代码中考虑这一事实。

Ani*_*gar 6

我通过将'name'识别人的身份作为钥匙做了一些补充。

方法

该方法是我对值进行了评分,该值进一步用于根据给定条件过滤最终对。

厨房评分

对于厨房分数,我们使用:

  • 人没有厨房:0
  • 人有厨房:1
  • 人有厨房,但仅在紧急情况下:0.5

厨房的条件逻辑

我们检查[记录1的厨房分数] + [记录2的厨房分数]是否大于零。由于将出现以下情况:

  1. 两个成员都没有厨房(总和为0)[不包括> 0条件]
  2. 两个成员都有厨房(总和为2)
  3. 一个成员有厨房,其他成员没有厨房(总和为1)
  4. 都有紧急厨房(总和为1)
  5. 一个有急救厨房,另一个有急救厨房(总和为1.5)
  6. 一个成员拥有急救厨房,其他成员则没有厨房(总和为0.5)

食物计分

对于食物评分,我们使用了:

  • 食物= 0->肉食者:-1
  • 食物= 1->没关系:0
  • 食物= 2->素食主义者:1
  • 食物= 3->素食:1

食物的条件逻辑

我们检查,如果* [记录1的比分食品] * [记录2的比分食品] *是大于或等于。由于将出现以下情况:

  1. 两个成员都是肉食者:-1 x -1 = 1 [已包括]
  2. 成员之一是食肉者和其他素食主义者:-1 x 1 = -1 [已排除]
  3. 成员之一是食肉者,其他无关紧要:-1 x 0 = 0 [包括在内]
  4. 成员之一是素食主义者或素食主义者,而其他无关紧要:1 x 0 = 0 [包括在内]
  5. 两个成员都是素食主义者:1 x 1 = 1 [包括在内]

年龄段评分

为了给年龄组评分,我们为这些组分配了一些值:

  • 10-18:1
  • 18-22:2
  • 22-26:3
  • 26-29:4
  • 29-34:5
  • 34-40:6
  • 40-45:7
  • 45-55:8
  • 55-75:9

年龄分数计算

为了计算年龄得分,使用了以下公式: age_score = round((1 - (abs(Age Group Value Person 1 - Age Group Value of Person 2) / 10)), 2)

在上面的公式中,我们的计算如下:

  1. 首先,我们计算了两个人年龄组之间的差值的绝对值。
  2. 然后我们将其除以10进行归一化。
  3. 此外,我们从1中减去了该值以求距离的倒数,因此在此步骤之后,对于相似或相近年龄组的人,其值较高,而对不同或相近年龄组的人的值较低。

情况如下:

  1. 18-22和18-22: round(1 - (abs(2 - 2) / 10), 2) = 1.0
  2. 45-55和45-55: round(1 - (abs(8 - 8) / 10), 2) = 1.0
  3. 18-22和45-55: round(1 - (abs(2 - 8) / 10), 2) = 0.4
  4. 10-18和55-75: round(1 - (abs(1 - 9) / 10), 2) = 0.2

最终分数计算

为了计算最终分数,我们使用了:

Final Score = Food Score + Kitchen Score + Age Score

然后,我们对最终得分的数据进行了排序,以获得最佳配对。

解决方案代码

import pandas as pd
import numpy as np

# Creating the DataFrame, here I have added the attribute 'name' for identifying the record.
df = pd.DataFrame({
    'name' : ['jacob', 'mary', 'rick', 'emily', 'sabastein', 'anna', 
              'christina', 'allen', 'jolly', 'rock', 'smith', 'waterman', 
              'mimi', 'katie', 'john', 'rose', 'leonardo', 'cinthy', 'jim', 
              'paul'],
    'sex' : ['m', 'f', 'm', 'f', 'm', 'f', 'f', 'm', 'f', 'm', 'm', 'm', 'f', 
             'f', 'm', 'f', 'm', 'f', 'm', 'm'],
    'food' : [0, 0, 1, 3, 2, 3, 1, 0, 0, 3, 3, 2, 1, 2, 1, 0, 1, 0, 3, 1],
    'age' : ['10-18', '22-26', '29-34', '40-45', '18-22', '34-40', '55-75',
             '45-55', '26-29', '26-29', '18-22', '55-75', '22-26', '45-55', 
             '10-18', '22-26', '40-45', '45-55', '10-18', '29-34'],
    'kitchen' : [0, 1, 2, 0, 1, 2, 2, 1, 0, 0, 1, 0, 1, 1, 1, 0, 2, 0, 2, 1],
})

# Adding a normalized field 'k_scr' for kitchen
df['k_scr'] = np.where((df['kitchen'] == 2), 0.5, df['kitchen'])

# Adding a normalized field 'f_scr' for food
df['f_scr'] = np.where((df['food'] == 1), 0, df['food'])
df['f_scr'] = np.where((df['food'] == 0), -1, df['f_scr'])
df['f_scr'] = np.where((df['food'] == 2), 1, df['f_scr'])
df['f_scr'] = np.where((df['food'] == 3), 1, df['f_scr'])

# Adding a normalized field 'a_scr' for age
df['a_scr'] = np.where((df['age'] == '10-18'), 1, df['age'])
df['a_scr'] = np.where((df['age'] == '18-22'), 2, df['a_scr'])
df['a_scr'] = np.where((df['age'] == '22-26'), 3, df['a_scr'])
df['a_scr'] = np.where((df['age'] == '26-29'), 4, df['a_scr'])
df['a_scr'] = np.where((df['age'] == '29-34'), 5, df['a_scr'])
df['a_scr'] = np.where((df['age'] == '34-40'), 6, df['a_scr'])
df['a_scr'] = np.where((df['age'] == '40-45'), 7, df['a_scr'])
df['a_scr'] = np.where((df['age'] == '45-55'), 8, df['a_scr'])
df['a_scr'] = np.where((df['age'] == '55-75'), 9, df['a_scr'])

# Printing DataFrame after adding normalized score values
print(df)

commonarr = [] # Empty array for our output
dfarr = np.array(df) # Converting DataFrame to Numpy Array
for i in range(len(dfarr) - 1): # Iterating the Array row
    for j in range(i + 1, len(dfarr)): # Iterating the Array row + 1
        # Check for Food Condition to include relevant records
        if dfarr[i][6] * dfarr[j][6] >= 0: 
            # Check for Kitchen Condition to include relevant records
            if dfarr[i][5] + dfarr[j][5] > 0:
                row = []
                # Appending the names
                row.append(dfarr[i][0])
                row.append(dfarr[j][0])
                # Appending the final score
                row.append((dfarr[i][6] * dfarr[j][6]) +
                           (dfarr[i][5] + dfarr[j][5]) +
                           (round((1 - (abs(dfarr[i][7] -
                                            dfarr[j][7]) / 10)), 2)))

                # Appending the row to the Final Array
                commonarr.append(row)

# Converting Array to DataFrame
ndf = pd.DataFrame(commonarr)

# Sorting the DataFrame on Final Score
ndf = ndf.sort_values(by=[2], ascending=False)
print(ndf)
Run Code Online (Sandbox Code Playgroud)

输入/具有分数的中间数据框

         name sex  food    age  kitchen  k_scr  f_scr a_scr
0       jacob   m     0  10-18        0    0.0     -1     1
1        mary   f     0  22-26        1    1.0     -1     3
2        rick   m     1  29-34        2    0.5      0     5
3       emily   f     3  40-45        0    0.0      1     7
4   sabastein   m     2  18-22        1    1.0      1     2
5        anna   f     3  34-40        2    0.5      1     6
6   christina   f     1  55-75        2    0.5      0     9
7       allen   m     0  45-55        1    1.0     -1     8
8       jolly   f     0  26-29        0    0.0     -1     4
9        rock   m     3  26-29        0    0.0      1     4
10      smith   m     3  18-22        1    1.0      1     2
11   waterman   m     2  55-75        0    0.0      1     9
12       mimi   f     1  22-26        1    1.0      0     3
13      katie   f     2  45-55        1    1.0      1     8
14       john   m     1  10-18        1    1.0      0     1
15       rose   f     0  22-26        0    0.0     -1     3
16   leonardo   m     1  40-45        2    0.5      0     7
17     cinthy   f     0  45-55        0    0.0     -1     8
18        jim   m     3  10-18        2    0.5      1     1
19       paul   m     1  29-34        1    1.0      0     5
Run Code Online (Sandbox Code Playgroud)

输出量

             0          1    2
48   sabastein      smith  4.0
10        mary      allen  3.5
51   sabastein      katie  3.4
102      smith        jim  3.4
54   sabastein        jim  3.4
99       smith      katie  3.4
61        anna      katie  3.3
45   sabastein       anna  3.1
58        anna      smith  3.1
14        mary       rose  3.0
12        mary       mimi  3.0
84       allen     cinthy  3.0
98       smith       mimi  2.9
105   waterman      katie  2.9
11        mary      jolly  2.9
50   sabastein       mimi  2.9
40       emily      katie  2.9
52   sabastein       john  2.9
100      smith       john  2.9
90        rock      smith  2.8
47   sabastein       rock  2.8
0        jacob       mary  2.8
17        mary       paul  2.8
13        mary       john  2.8
119      katie        jim  2.8
116       mimi       paul  2.8
111       mimi       john  2.8
103      smith       paul  2.7
85       allen       paul  2.7
120      katie       paul  2.7
..         ...        ...  ...
Run Code Online (Sandbox Code Playgroud)

该解决方案具有进一步的优化范围。