根据属性匹配两个人

2024-06-07 03:40:15 发布

您现在位置:Python中文网/ 问答频道 /正文

我有一个不同人的数据帧。每一行都包含描述个人特征的属性。基本上,我需要一个过滤器或匹配算法加权特定的属性。数据帧如下所示:

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],
})

数据帧df如下所示:

^{pr2}$

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

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

    厨房=0-->人没有厨房

    厨房=1-->人有厨房

    厨房=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行),我需要找到一个自动化的解决方案。一个解决方案,它给了我数据帧、字典或其他东西中的最佳对。在

我真的不知道如何处理这个问题。我正在寻找堆栈溢出的类似问题,但我没有找到任何合适的。基本上,这只是太理论化了。我也找不到真正适合我问题的东西。在

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

背景:目标是结对参加一些业余活动。所以我认为,相同或相似年龄组的人有着相同的兴趣,所以我想在我的代码中考虑这个事实。在


Tags: 数据算法过滤器df字典属性food特征
3条回答

我做了一个加法,把'name'作为一个键来识别这个人。在

接近

方法是,我对值进行评分,然后根据给定的条件进一步用于筛选最终对。在

厨房计分

我们使用的厨房评分:

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

厨房if条件逻辑

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

  1. 两个成员都没有厨房(总和为0)[不包括在>;0条件下]
  2. 两位成员都有厨房(总数为2)
  3. 一个成员有厨房,另一个没有厨房(总和为1)
  4. 两个都有应急厨房(总和为1)
  5. 一个有应急厨房,另一个有厨房(总和为1.5)
  6. 一名成员有应急厨房,另一名成员没有厨房(总和为0.5)

食物得分

我们使用的食物分数:

  • 食客:1>;肉
  • 食物=1>;无所谓:0
  • 食物=2>;素食主义者:1
  • 食物=3>;素食者:1

食品的if条件逻辑

我们检查*[记录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)

带分数的输入/中间数据帧

^{pr2}$

输出

             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
..         ...        ...  ...

这个解决方案还有进一步的优化范围。在

好吧,让我们测试一下厨房。在

for I in(kitchen):
    if (I != 0):
        print("Kitchen Found)
    else:
        print("No kitchen")

好吧,现在我们已经在有厨房的人的家里找到了厨房,让我们找到没有厨房的人有相似的食物偏好。让我们创建一个变量来告诉我们有多少人有一个厨房(x)。我们也让person变量用于计算人数。在

^{pr2}$

我现在正在做年龄调整

这对我来说是个很有趣的问题。有几种方法可以解决这个问题。我将向您陈述一个,但会将您链接到another solution,我觉得这是某种关联。在

一种可能的方法是在dataframe中创建一个额外的列,包括引用给定属性的“code”。例如:

    sex  food  age      kitchen   code
0   m    0     young    0         0y0
1   f    0     young    1         0y1
2   m    1     young    2         1y2
3   f    3     old      0         3o0
4   m    4     young    1         4y1
5   f    3     young    2         3y2

这个“代码”是由你的属性组成的。因为性别无关紧要,代码中的第一个符号代表“食物”,第二个符号代表“年龄”,第三个符号代表“厨房”。在

^{pr2}$

根据这些代码,你可以想出一个模式。我建议您为此使用Regular Expressions。你可以这样写:

import re
haskitchen = r'(\S\S1)
hasnokitchen = r'(\S\S0)
df_dict = df.to_dict

match_kitchen = re.findall(haskitchen, df_dict)
match_nokitchen = re.dinfall(hasnokitchen, df_dict)

kitchendict["Has kitchen"] = [match_kitchen]
kitchendict["Has no kitchen"] = [match_notkitchen]

基于此,您可以对条目进行循环,并按您的需要将它们组合在一起。可能有一个更简单的解决方案,我没有验证代码,但这只是我想到的。有一点是肯定的:使用正则表达式进行匹配。

相关问题 更多 >