我有一个与其他人在一起的数据框。每行都包含表征个人的属性。基本上,我需要权重特定属性的过滤器或匹配算法之类的东西。数据框如下所示:
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
如下所示:
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
我正在寻找一种算法,该算法将数据帧中的所有人分组。我的计划是根据以下属性找到两个人对:
一个人必须有厨房(厨房= 1)
至少要有一个厨房是很重要的。
厨房= 0->人没有厨房
厨房= 1->人有厨房
kitchen = 2->人有厨房,但只有在紧急情况下(没有其他选择时)
相同的食物偏好
food = 0->食肉者
food = 1->没关系
food = 2->素食主义者
food = 3->素食主义者
食肉者(食物= 0)可以与不关心食物偏好(食物= 1)但不能与素食主义者或素食者相匹配的人搭配。素食主义者(食物= 2)最适合素食主义者(食物= 3),并且在必要时可以搭配食物= 1。等等...
类似年龄
共有9个年龄段:10-18岁; 18-22; 22-26; 26-29、29-34; 34-40; 40-45; 45-55和55-75。同一年龄段的人匹配得很好。年轻的年龄段与年龄较大的年龄段的匹配度不是很好。相似年龄段的人匹配得更好。没有明确定义的条件。 “老”和“年轻”的含义是相对的。
性别无关紧要。有许多可能的配对组合。因为我的实际数据帧很长(3000行),所以我需要找到一个自动化的解决方案。一种解决方案,可以为我提供数据框或字典或其他内容中的最佳配对。
我真的不知道该如何解决这个问题。我一直在寻找Stack Overflow上的类似问题,但没有找到合适的方法。在大多数情况下,这只是理论上的问题。另外,我找不到任何适合我问题的东西。
我在这里的预期输出将是例如字典(不确定如何)或数据帧,其排序方式是每两行可以看作一对。
背景:目标是为一些业余时间活动配对。因此,我认为处于相同或相似年龄段的人们具有相同的兴趣,因此我想在我的代码中考虑这个事实。
答案 0 :(得分:4)
我已经通过添加'name'
作为识别该人的密钥来进行加法。
该方法是我对值进行了评分,该值进一步用于根据给定条件过滤最终对。
我们使用的厨房评分:
我们检查 [记录1的厨房分数] + [记录2的厨房分数] 是否大于零。由于将出现以下情况:
我们使用的食物评分:
我们检查* [记录1的食物得分] * [记录2的食物得分] *是否大于等于为零。由于将出现以下情况:
对于得分年龄组,我们为这些组分配了一些值:
为了计算年龄得分,使用了以下公式:
age_score = round((1 - (abs(Age Group Value Person 1 - Age Group Value of Person 2) / 10)), 2)
在上面的公式中,我们的计算如下:
情况如下:
round(1 - (abs(2 - 2) / 10), 2) = 1.0
round(1 - (abs(8 - 8) / 10), 2) = 1.0
round(1 - (abs(2 - 8) / 10), 2) = 0.4
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)
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
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
.. ... ... ...
此解决方案具有进一步的优化范围。
答案 1 :(得分:1)
对我来说,这似乎是一个非常有趣的问题。有几种方法可以解决此问题。我将向您声明一个,但会将您链接到我认为与之相关的another solution。
一种可能的方法是在数据框中创建一个附加列,包括一个引用给定属性的“代码”。例如:
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
此“代码”由您属性的缩写组成。由于性别无关紧要,因此代码中的第一个符号代表“食物”,第二个符号代表“年龄”,第三个符号代表“厨房”。
4y1 = food 4, age young, kitchen 1.
根据这些代码,您可以提出一个模式。我建议您为此使用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]
基于此,您可以遍历条目并将其按需要组合在一起。可能有一个更简单的解决方案,而我没有证明代码,但这只是我的想法。可以肯定的是:使用正则表达式进行匹配。
答案 2 :(得分:1)
好吧,我们来测试一下厨房。
for I in(kitchen):
if (I != 0):
print("Kitchen Found)
else:
print("No kitchen")
好吧,现在我们已经在拥有厨房房屋的人中找到了厨房,让我们找到没有厨房的人,他们的食物偏好相似。让我们创建一个变量,告诉我们有多少人拥有厨房(x)。让我们也将人员变量设为计数人员。
people = 0
x = 0
for I in(kitchen):
x = x + 1
for A in (food):
if (I != 0):
x = x + 1
print("Kitchen Found)
else:
print("No kitchen")
for J in(food):
if(i == J):
print("food match found")
elif(A == 0):
if(J == 1):
print("food match found for person" + x)
elif(A == 2 or A == 3):
if(J == 2 or J == 3 or J == 1):
print("food match found for person" + x)
我目前正在调整年龄部分