Сопоставление двух людей вместе на основе атрибутов - PullRequest
0 голосов
/ 01 января 2019

У меня есть датафрейм с разными людьми.Каждая строка содержит атрибуты, которые характеризуют отдельного человека.В основном мне нужно что-то вроде фильтра или алгоритма сопоставления, который взвешивает определенные атрибуты.Кадр данных выглядит следующим образом:

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. Один человек должен иметь кухню (kitchen = 1)
    Это важночто хотя бы у одного человека есть кухня.

    кухня = 0 -> у человека нет кухни

    кухня = 1 -> у человека есть кухня

    кухня = 2 -> у человека есть кухня, но тольков чрезвычайных ситуациях (когда нет другого выбора)

  2. Те же предпочтения в еде

    еда = 0 -> мясоед

    еда = 1 -> не имеет значения

    еда = 2 -> веганский

    еда = 3 -> вегетарианец

    мясоед (еда = 0)может быть сопоставлен с человеком, который не заботится о предпочтениях в еде (food = 1), но не может сравниться с веганом или вегетарианцем.Веган (еда = 2) лучше всего подходит для вегетарианца (еда = 3) и, если необходимо, может пойти с едой = 1.И так далее ...

  3. Аналогичный возраст

    Существует девять возрастных групп: 10-18;18-22;22-26;26-29, 29-34;34-40;40-45;45-55 и 55-75.Люди в одной возрастной группе идеально подходят друг другу.Молодые возрастные группы с более старшими возрастными группами не очень хорошо совпадают.Подобные возрастные группы соответствуют немного лучше.Нет четко определенного условия.Значение «старый» и «молодой» является относительным.

Пол не имеет значения.Есть много возможных комбинаций пар.Поскольку мой фактический фрейм данных очень длинный (3000 строк), мне нужно найти автоматизированное решение.Решение, которое дает мне лучшие пары в кадре данных или словаре или что-то еще.

Я действительно не знаю, как решить эту проблему.Я искал похожие проблемы в переполнении стека, но не нашел ничего подходящего.В основном это было слишком теоретически.Также я не смог найти ничего, что действительно соответствовало бы моей проблеме.

Мой ожидаемый вывод здесь был бы, например, словарь (не уверен, как) или фрейм данных, который отсортирован так, чтобы можно было видеть каждые две строки.как одна пара.

Справочная информация: Цель состоит в том, чтобы создать пары для некоторых видов деятельности в свободное время.Поэтому я думаю, что люди в одинаковых или похожих возрастных группах имеют одинаковый интерес, поэтому я хочу учесть этот факт в своем коде.

Ответы [ 3 ]

0 голосов
/ 01 января 2019

Что ж, давайте проверим кухню.

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

Хорошо, теперь, когда мы нашли кухню в людях, у которых есть кухонные дома, давайте найдем людей без кухни, кто-то с подобными предпочтениями в еде.Давайте создадим переменную, которая скажет нам, сколько людей имеют кухню (х).Давайте также сделаем переменную person для подсчета людей.

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)

В настоящее время я работаю над тем, чтобы скорректировать возрастную часть

0 голосов
/ 01 января 2019

Я сделал дополнение, поставив 'name' в качестве ключа для идентификации человека.

Подход

Подход заключается в том, что я оценил значения, которые в дальнейшем используются для фильтрациифинальные пары в соответствии с заданными условиями.

Подсчет очков для кухни

Для оценки кухни мы использовали:

  • У человека нет кухни: 0
  • У человека есть кухня: 1
  • У человека есть кухня, но только в чрезвычайной ситуации: 0,5

если Условие Логика для кухни

Мы проверяем, что если [кухняоценка записи 1] + [кухонная оценка записи 2] на больше нуля .В следующих случаях:

  1. У обоих участников нет кухни (сумма будет 0) [ИСКЛЮЧЕНО при> 0 условии]
  2. Оба участника имеюткухня (сумма будет 2)
  3. У одного участника есть кухня, а у другого нет кухни (сумма будет 1)
  4. Оба имеют аварийную кухню (сумма будет 1)
  5. Один имеет аварийную кухню, а другой - кухню (сумма будет 1,5)
  6. Один участник имеет аварийную кухню, а другой не имеет кухни (сумма будет 0,5)

Подсчет баллов за еду

Для оценки продуктов мы использовали:

  • food = 0 -> мясоед: -1
  • food = 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)

Входной / промежуточный фрейм данных со счетами

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

Это решение имеет дополнительную область оптимизации.

0 голосов
/ 01 января 2019

Это кажется мне очень интересной проблемой.Есть несколько способов решить эту проблему.Я скажу вам одно, но свяжу вас с другим решением , которое, как мне кажется, каким-то образом связано.

Возможный подход может заключаться в создании дополнительного столбца в вашем фрейме данных, включая«код», который ссылается на данные атрибуты. Например:

    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.

На основании этих кодов вы можете создать шаблон.Для этого я рекомендую вам использовать Регулярные выражения .Затем вы можете написать что-то вроде этого:

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]

Исходя из этого, вы можете циклически перебирать записи и собирать их вместе, как вы хотите.Возможно, есть гораздо более простое решение, и я не проверял код, но это просто пришло мне в голову.Одно можно сказать наверняка: Используйте регулярные выражения для сопоставления.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...